feat(host-agent): add mcp-token CLI subcommand
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -10,6 +10,7 @@ from host_agent.app import create_application
|
|||||||
from host_agent.config import load_host_agent_config
|
from host_agent.config import load_host_agent_config
|
||||||
from host_agent.instance_lock import InstanceAlreadyRunningError
|
from host_agent.instance_lock import InstanceAlreadyRunningError
|
||||||
from host_agent.local_account import LocalAccountStore
|
from host_agent.local_account import LocalAccountStore
|
||||||
|
from host_agent.mcp_token import McpTokenStore
|
||||||
|
|
||||||
|
|
||||||
class LocalAccountSetupError(RuntimeError):
|
class LocalAccountSetupError(RuntimeError):
|
||||||
@@ -20,8 +21,16 @@ def main(argv: Sequence[str] | None = None) -> None:
|
|||||||
parser = argparse.ArgumentParser(description="Run the Device Host Agent")
|
parser = argparse.ArgumentParser(description="Run the Device Host Agent")
|
||||||
subparsers = parser.add_subparsers(dest="command")
|
subparsers = parser.add_subparsers(dest="command")
|
||||||
subparsers.add_parser("setup", help="Create the local operator account")
|
subparsers.add_parser("setup", help="Create the local operator account")
|
||||||
|
subparsers.add_parser(
|
||||||
|
"mcp-token",
|
||||||
|
help="Print the MCP server bearer token (generating if missing)",
|
||||||
|
)
|
||||||
args = parser.parse_args(argv)
|
args = parser.parse_args(argv)
|
||||||
|
|
||||||
|
if args.command == "mcp-token":
|
||||||
|
_print_mcp_token()
|
||||||
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if args.command == "setup":
|
if args.command == "setup":
|
||||||
_run_setup()
|
_run_setup()
|
||||||
@@ -54,6 +63,12 @@ def _run_setup() -> None:
|
|||||||
print(f"Local account '{account.username}' created.")
|
print(f"Local account '{account.username}' created.")
|
||||||
|
|
||||||
|
|
||||||
|
def _print_mcp_token() -> None:
|
||||||
|
config = load_host_agent_config()
|
||||||
|
store = McpTokenStore(config.identity_path.parent / "host_mcp_token.json")
|
||||||
|
print(store.load_or_create().token)
|
||||||
|
|
||||||
|
|
||||||
def _resolve_config_with_local_account():
|
def _resolve_config_with_local_account():
|
||||||
config = load_host_agent_config()
|
config = load_host_agent_config()
|
||||||
store = LocalAccountStore(config.local_account_path)
|
store = LocalAccountStore(config.local_account_path)
|
||||||
|
|||||||
@@ -146,3 +146,19 @@ def test_duplicate_instance_exits_with_clear_error(
|
|||||||
err = capsys.readouterr().err
|
err = capsys.readouterr().err
|
||||||
assert "another Host Agent instance" in err
|
assert "another Host Agent instance" in err
|
||||||
assert str(lock_path) in err
|
assert str(lock_path) in err
|
||||||
|
|
||||||
|
|
||||||
|
def test_mcp_token_subcommand_prints_token(tmp_path, capsys, monkeypatch) -> None:
|
||||||
|
monkeypatch.setenv("HOST_AGENT_IDENTITY_PATH", str(tmp_path / "host_identity.json"))
|
||||||
|
monkeypatch.setenv("HOST_AGENT_LOCAL_ACCOUNT_PATH", str(tmp_path / "host_local_account.json"))
|
||||||
|
# Also set control plane URL to satisfy config loading
|
||||||
|
monkeypatch.setenv("HOST_AGENT_CONTROL_PLANE_URL", "https://cloud.example")
|
||||||
|
from host_agent.cli import main
|
||||||
|
|
||||||
|
main(["mcp-token"])
|
||||||
|
out = capsys.readouterr().out.strip()
|
||||||
|
assert len(out) >= 40 # token is ~43 chars
|
||||||
|
# Subsequent invocation prints the same token (idempotent).
|
||||||
|
main(["mcp-token"])
|
||||||
|
out2 = capsys.readouterr().out.strip()
|
||||||
|
assert out == out2
|
||||||
|
|||||||
Reference in New Issue
Block a user