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
21 changes: 20 additions & 1 deletion backend/app/assistant_tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,26 @@
MAX_FILE_LINES = 120
MAX_SEARCH_RESULTS = 12
BLOCKED_NAMES = {".env", ".git", ".ssh", "id_rsa", "id_ed25519"}
DEFAULT_MCP_URL = "http://127.0.0.1:3000/mcp/"


def _local_mcp_url() -> str:
"""Return this process's local MCP endpoint.

``orbit run`` may select a port above the requested one when it is already
occupied. It passes that selected port through ``ORBIT_PORT`` to keep
generated MCP configuration from pointing at the process that occupied it.
"""
configured_port = os.environ.get("ORBIT_PORT", "3000").strip()
try:
port = int(configured_port)
except ValueError:
port = 3000
if not 1 <= port <= 65535:
port = 3000
return f"http://127.0.0.1:{port}/mcp/"


DEFAULT_MCP_URL = _local_mcp_url()


def _terminal_visible() -> bool:
Expand Down
10 changes: 10 additions & 0 deletions backend/tests/test_assistant_graph.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from app import assistant_tools
from app.assistant_graph import DEFAULT_MCP_URL, LocalMcpTools, OrbitAssistantGraph, build_assistant_prompt
from app.providers import ModelSettings

Expand Down Expand Up @@ -56,6 +57,15 @@ def test_assistant_prompt_uses_local_mcp_as_the_control_room_source_of_truth():
assert "Assistant: Earlier answer" in prompt


def test_local_mcp_url_uses_the_effective_server_port(monkeypatch):
monkeypatch.setenv("ORBIT_PORT", "3001")

assert assistant_tools._local_mcp_url() == "http://127.0.0.1:3001/mcp/"

monkeypatch.setenv("ORBIT_PORT", "not-a-port")
assert assistant_tools._local_mcp_url() == "http://127.0.0.1:3000/mcp/"


def test_assistant_prompt_prioritizes_ui_tools_for_browser_ui_requests():
prompt = build_assistant_prompt("What screen is open?", [], "en", ui_enabled=True)

Expand Down
5 changes: 4 additions & 1 deletion bin/orbit.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ if (!Number.isInteger(requestedPort) || requestedPort < 1 || requestedPort > 655
const port = await nextAvailablePort(requestedPort, host)
const localUrl = `http://127.0.0.1:${port}`
console.log(`OpenOrbit is starting. Open ${localUrl}`)
console.log(`MCP endpoint: ${localUrl}/mcp/`)
if (port !== requestedPort) {
console.log(`Port ${requestedPort} is in use; using ${port} instead.`)
}
Expand All @@ -76,7 +77,9 @@ if (process.env.ORBIT_PUBLIC_URL) {
const server = spawn(venvPython, ['-m', 'uvicorn', 'app.main:app', '--app-dir', 'backend', '--host', host, '--port', port], {
cwd: root,
stdio: 'inherit',
env: { ...process.env, ...(appData ? { ORBIT_APP_DATA: appData } : {}) },
// Keep the server's generated local MCP configuration aligned with the
// port selected above when the requested port was already occupied.
env: { ...process.env, ORBIT_PORT: String(port), ...(appData ? { ORBIT_APP_DATA: appData } : {}) },
})
process.on('SIGINT', () => server.kill('SIGINT'))
process.on('SIGTERM', () => server.kill('SIGTERM'))
Expand Down
Loading