diff --git a/doc/news/DM-46979.feature.rst b/doc/news/DM-46979.feature.rst
new file mode 100644
index 000000000..7a486dd0e
--- /dev/null
+++ b/doc/news/DM-46979.feature.rst
@@ -0,0 +1,2 @@
+Add SAL scripts to park and unpark the TMA for ``maintel``.
+
diff --git a/python/lsst/ts/standardscripts/data/scripts/maintel/mtmount/park_mount.py b/python/lsst/ts/standardscripts/data/scripts/maintel/mtmount/park_mount.py
new file mode 100755
index 000000000..1c65929d5
--- /dev/null
+++ b/python/lsst/ts/standardscripts/data/scripts/maintel/mtmount/park_mount.py
@@ -0,0 +1,27 @@
+#!/usr/bin/env python
+# This file is part of ts_standardscripts
+#
+# Developed for the LSST Telescope and Site Systems.
+# This product includes software developed by the LSST Project
+# (https://www.lsst.org).
+# See the COPYRIGHT file at the top-level directory of this distribution
+# for details of code ownership.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+import asyncio
+
+from lsst.ts.standardscripts.maintel.mtmount import ParkMount
+
+asyncio.run(ParkMount.amain())
diff --git a/python/lsst/ts/standardscripts/data/scripts/maintel/mtmount/unpark_mount.py b/python/lsst/ts/standardscripts/data/scripts/maintel/mtmount/unpark_mount.py
new file mode 100755
index 000000000..e2604bdad
--- /dev/null
+++ b/python/lsst/ts/standardscripts/data/scripts/maintel/mtmount/unpark_mount.py
@@ -0,0 +1,27 @@
+#!/usr/bin/env python
+# This file is part of ts_standardscripts
+#
+# Developed for the LSST Telescope and Site Systems.
+# This product includes software developed by the LSST Project
+# (https://www.lsst.org).
+# See the COPYRIGHT file at the top-level directory of this distribution
+# for details of code ownership.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+import asyncio
+
+from lsst.ts.standardscripts.maintel.mtmount import UnparkMount
+
+asyncio.run(UnparkMount.amain())
diff --git a/python/lsst/ts/standardscripts/maintel/mtmount/__init__.py b/python/lsst/ts/standardscripts/maintel/mtmount/__init__.py
new file mode 100644
index 000000000..7d4e0f359
--- /dev/null
+++ b/python/lsst/ts/standardscripts/maintel/mtmount/__init__.py
@@ -0,0 +1,23 @@
+# This file is part of ts_standardscripts
+#
+# Developed for the LSST Telescope and Site Systems.
+# This product includes software developed by the LSST Project
+# (https://www.lsst.org).
+# See the COPYRIGHT file at the top-level directory of this distribution
+# for details of code ownership.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+from .park_mount import *
+from .unpark_mount import *
diff --git a/python/lsst/ts/standardscripts/maintel/mtmount/park_mount.py b/python/lsst/ts/standardscripts/maintel/mtmount/park_mount.py
new file mode 100644
index 000000000..03300847f
--- /dev/null
+++ b/python/lsst/ts/standardscripts/maintel/mtmount/park_mount.py
@@ -0,0 +1,109 @@
+# This file is part of ts_standardscripts
+#
+# Developed for the LSST Telescope and Site Systems.
+# This product includes software developed by the LSST Project
+# (https://www.lsst.org).
+# See the COPYRIGHT file at the top-level directory of this distribution
+# for details of code ownership.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .``
+
+__all__ = ["ParkMount"]
+
+import yaml
+from lsst.ts import salobj
+from lsst.ts.observatory.control.maintel.mtcs import MTCS, MTCSUsages
+from lsst.ts.xml.enums import MTMount
+
+
+class ParkMount(salobj.BaseScript):
+ """Park Mount for the MTMount.
+
+ Parameters
+ ----------
+ index : `int`
+ Index of Script SAL component.
+
+ Notes
+ -----
+ **Checkpoints**
+
+ None
+ """
+
+ def __init__(self, index):
+ super().__init__(index=index, descr="Park Mount for the MTMount.")
+
+ self.mtcs = None
+
+ @classmethod
+ def get_schema(cls):
+ schema_yaml = """
+ $schema: http://json-schema.org/draft-07/schema#
+ $id: https://github.com/lsst-ts/ts_standardscripts/maintel/mtmount/park_mount.yaml
+ title: ParkMount v1
+ description: Configuration for ParkMount.
+ type: object
+ properties:
+ position:
+ description: The position to park the MTMount.
+ type: string
+ enum: ["ZENITH", "HORIZON"]
+ ignore:
+ description: >-
+ CSCs from the group to ignore in status check. Name must
+ match those in self.group.components, e.g.; hexapod_1.
+ type: array
+ items:
+ type: string
+ additionalProperties: false
+ required: [position]
+ """
+ return yaml.safe_load(schema_yaml)
+
+ def set_metadata(self, metadata):
+ pass
+
+ async def configure(self, config):
+ """Configure script.
+
+ Parameters
+ ----------
+ config : `types.SimpleNamespace`
+ Script configuration, as defined by `schema`.
+ """
+ self.config = config
+ self.position = MTMount.ParkPosition[config.position]
+
+ if self.mtcs is None:
+ self.mtcs = MTCS(
+ domain=self.domain,
+ intended_usage=MTCSUsages.Slew | MTCSUsages.StateTransition,
+ log=self.log,
+ )
+ await self.mtcs.start_task
+
+ if hasattr(self.config, "ignore"):
+ for comp in self.config.ignore:
+ if comp not in self.mtcs.components_attr:
+ self.log.warning(
+ f"Component {comp} not in CSC Group. "
+ f"Must be one of {self.mtcs.components_attr}. Ignoring."
+ )
+ else:
+ self.log.debug(f"Ignoring component {comp}.")
+ setattr(self.mtcs.check, comp, False)
+
+ async def run(self):
+ await self.mtcs.park_mount(position=self.position)
diff --git a/python/lsst/ts/standardscripts/maintel/mtmount/unpark_mount.py b/python/lsst/ts/standardscripts/maintel/mtmount/unpark_mount.py
new file mode 100644
index 000000000..e098b1c96
--- /dev/null
+++ b/python/lsst/ts/standardscripts/maintel/mtmount/unpark_mount.py
@@ -0,0 +1,101 @@
+#
+# Developed for the LSST Telescope and Site Systems.
+# This product includes software developed by the LSST Project
+# (https://www.lsst.org).
+# See the COPYRIGHT file at the top-level directory of this distribution
+# for details of code ownership.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .``
+
+__all__ = ["UnparkMount"]
+
+import yaml
+from lsst.ts import salobj
+from lsst.ts.observatory.control.maintel.mtcs import MTCS, MTCSUsages
+
+
+class UnparkMount(salobj.BaseScript):
+ """Un-park Mount for the MTMount.
+
+ Parameters
+ ----------
+ index : `int`
+ Index of Script SAL component.
+
+ Notes
+ -----
+ **Checkpoints**
+
+ None
+ """
+
+ def __init__(self, index):
+ super().__init__(index=index, descr="Unpark Mount for the MTMount.")
+
+ self.mtcs = None
+
+ @classmethod
+ def get_schema(cls):
+ schema_yaml = """
+ $schema: http://json-schema.org/draft-07/schema#
+ $id: https://github.com/lsst-ts/ts_standardscripts/maintel/mtmount/unpark_mount.yaml
+ title: UnparkMount v1
+ description: Configuration for UnparkMount.
+ type: object
+ properties:
+ ignore:
+ description: >-
+ CSCs from the group to ignore in status check. Name must
+ match those in self.group.components, e.g.; hexapod_1.
+ type: array
+ items:
+ type: string
+ additionalProperties: false
+ """
+ return yaml.safe_load(schema_yaml)
+
+ def set_metadata(self, metadata):
+ pass
+
+ async def configure(self, config):
+ """Configure script.
+
+ Parameters
+ ----------
+ config : `types.SimpleNamespace`
+ Script configuration, as defined by `schema`.
+ """
+ self.config = config
+
+ if self.mtcs is None:
+ self.mtcs = MTCS(
+ domain=self.domain,
+ intended_usage=MTCSUsages.Slew | MTCSUsages.StateTransition,
+ log=self.log,
+ )
+ await self.mtcs.start_task
+
+ if hasattr(self.config, "ignore"):
+ for comp in self.config.ignore:
+ if comp not in self.mtcs.components_attr:
+ self.log.warning(
+ f"Component {comp} not in CSC Group. "
+ f"Must be one of {self.mtcs.components_attr}. Ignoring."
+ )
+ else:
+ self.log.debug(f"Ignoring component {comp}.")
+ setattr(self.mtcs.check, comp, False)
+
+ async def run(self):
+ await self.mtcs.unpark_mount()
diff --git a/tests/test_maintel_mtmount_park_mount.py b/tests/test_maintel_mtmount_park_mount.py
new file mode 100644
index 000000000..632666b46
--- /dev/null
+++ b/tests/test_maintel_mtmount_park_mount.py
@@ -0,0 +1,78 @@
+# This file is part of ts_standardscripts
+#
+# Developed for the LSST Telescope and Site Systems.
+# This product includes software developed by the LSST Project
+# (https://www.lsst.org).
+# See the COPYRIGHT file at the top-level directory of this distribution
+# for details of code ownership.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+import contextlib
+import unittest
+
+from lsst.ts import standardscripts
+from lsst.ts.standardscripts.maintel.mtmount import ParkMount
+from lsst.ts.xml.enums import MTMount
+
+
+class TestParkMount(
+ standardscripts.BaseScriptTestCase, unittest.IsolatedAsyncioTestCase
+):
+ async def basic_make_script(self, index):
+ self.script = ParkMount(index=index)
+ return (self.script,)
+
+ @contextlib.asynccontextmanager
+ async def make_dry_script(self):
+ async with self.make_script(self):
+ self.script.mtcs = unittest.mock.AsyncMock()
+ self.script.mtcs.assert_all_enabled = unittest.mock.AsyncMock()
+ self.script.mtcs.park_mount = unittest.mock.AsyncMock()
+ yield
+
+ async def test_executable(self):
+ scripts_dir = standardscripts.get_scripts_dir()
+ script_path = scripts_dir / "maintel" / "mtmount" / "park_mount.py"
+ await self.check_executable(script_path)
+
+ async def test_configure_ignore(self):
+ async with self.make_script():
+ components = ["mtptg"]
+ await self.configure_script(position="ZENITH", ignore=components)
+ assert self.script.mtcs.check.mtptg is False
+
+ async def test_configure_ignore_not_mtcs_component(self):
+ async with self.make_script():
+ # Test the ignore feature with one non-MTCS component.
+ components = ["not_mtcs_comp", "mtptg"]
+ await self.configure_script(position="ZENITH", ignore=components)
+ assert not hasattr(self.script.mtcs.check, "not_mtcs_comp")
+ assert self.script.mtcs.check.mtptg is False
+
+ async def test_park_zenith(self):
+ async with self.make_dry_script():
+ await self.configure_script(position="ZENITH")
+ await self.run_script()
+ self.script.mtcs.park_mount.assert_called_with(
+ position=MTMount.ParkPosition.ZENITH
+ )
+
+ async def test_park_horizon(self):
+ async with self.make_dry_script():
+ await self.configure_script(position="HORIZON")
+ await self.run_script()
+ self.script.mtcs.park_mount.assert_called_with(
+ position=MTMount.ParkPosition.HORIZON
+ )
diff --git a/tests/test_maintel_mtmount_unpark_mount.py b/tests/test_maintel_mtmount_unpark_mount.py
new file mode 100644
index 000000000..d3812ce25
--- /dev/null
+++ b/tests/test_maintel_mtmount_unpark_mount.py
@@ -0,0 +1,67 @@
+# This file is part of ts_standardscripts
+#
+# Developed for the LSST Telescope and Site Systems.
+# This product includes software developed by the LSST Project
+# (https://www.lsst.org).
+# See the COPYRIGHT file at the top-level directory of this distribution
+# for details of code ownership.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+import contextlib
+import unittest
+
+from lsst.ts import standardscripts
+from lsst.ts.standardscripts.maintel.mtmount import UnparkMount
+
+
+class TestUnparkMount(
+ standardscripts.BaseScriptTestCase, unittest.IsolatedAsyncioTestCase
+):
+ async def basic_make_script(self, index):
+ self.script = UnparkMount(index=index)
+ return (self.script,)
+
+ @contextlib.asynccontextmanager
+ async def make_dry_script(self):
+ async with self.make_script(self):
+ self.script.mtcs = unittest.mock.AsyncMock()
+ self.script.mtcs.assert_all_enabled = unittest.mock.AsyncMock()
+ self.script.mtcs.unpark_mount = unittest.mock.AsyncMock()
+ yield
+
+ async def test_executable(self):
+ scripts_dir = standardscripts.get_scripts_dir()
+ script_path = scripts_dir / "maintel" / "mtmount" / "unpark_mount.py"
+ await self.check_executable(script_path)
+
+ async def test_configure_ignore(self):
+ async with self.make_script():
+ components = ["mtptg"]
+ await self.configure_script(ignore=components)
+ assert self.script.mtcs.check.mtptg is False
+
+ async def test_configure_ignore_not_mtcs_component(self):
+ async with self.make_script():
+ # Test the ignore feature with one non-MTCS component.
+ components = ["not_mtcs_comp", "mtptg"]
+ await self.configure_script(ignore=components)
+ assert not hasattr(self.script.mtcs.check, "not_mtcs_comp")
+ assert self.script.mtcs.check.mtptg is False
+
+ async def test_run(self):
+ async with self.make_dry_script():
+ await self.configure_script()
+ await self.run_script()
+ self.script.mtcs.unpark_mount.assert_called_once()