topdesk-mcp 0.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ <!-- Use this file to provide workspace-specific custom instructions to Copilot. For more details, visit https://code.visualstudio.com/docs/copilot/copilot-customization#_use-a-githubcopilotinstructionsmd-file -->
2
+
3
+ This is an MCP Server project. You can find more info and examples at https://modelcontextprotocol.io/llms-full.txt
4
+
5
+ This MCP server exposes the Topdesk API using the TOPdeskPy SDK: https://github.com/TwinkelToe/TOPdeskPy
6
+
7
+ Reference the SDK documentation and MCP protocol documentation when generating code for this project.
@@ -0,0 +1,26 @@
1
+ on:
2
+ release:
3
+ types: [created]
4
+
5
+ jobs:
6
+ deploy:
7
+ runs-on: ubuntu-latest
8
+ permissions:
9
+ id-token: write
10
+ steps:
11
+ - uses: actions/checkout@v4
12
+ - name: Set up Python
13
+ uses: actions/setup-python@v5
14
+ with:
15
+ python-version: '3.12'
16
+ cache: pip
17
+ cache-dependency-path: '**/pyproject.toml'
18
+ - name: Build
19
+ run: |
20
+ pip install uv
21
+ uv venv
22
+ uv pip install setuptools wheel build
23
+ uv build
24
+
25
+ - name: Publish
26
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,25 @@
1
+ name: Run Pytest
2
+
3
+ on:
4
+ pull_request:
5
+ branches: [ master ]
6
+
7
+ jobs:
8
+ test:
9
+ runs-on: ubuntu-latest
10
+ steps:
11
+ - name: Checkout code
12
+ uses: actions/checkout@v4
13
+
14
+ - name: Set up Python
15
+ uses: actions/setup-python@v5
16
+ with:
17
+ python-version: '3.12'
18
+
19
+ - name: Run pytest
20
+ run: |
21
+ pip install uv
22
+ uv venv
23
+ uv pip install -e .
24
+ uv pip install -e ".[dev]"
25
+ uv run pytest
@@ -0,0 +1,5 @@
1
+ **/fastmcp-README.md
2
+ **/__pycache__
3
+ **/.pytest_cache
4
+ **/.venv
5
+ topdesk_mcp.log
@@ -0,0 +1,14 @@
1
+ {
2
+ // Use IntelliSense to learn about possible attributes.
3
+ // Hover to view descriptions of existing attributes.
4
+ // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5
+ "version": "0.2.0",
6
+ "configurations": [
7
+ {
8
+ "name": "Python Debugger: Module",
9
+ "type": "debugpy",
10
+ "request": "launch",
11
+ "module": "topdesk_mcp.main"
12
+ }
13
+ ]
14
+ }
@@ -0,0 +1,13 @@
1
+ {
2
+ "servers": {
3
+ "topdesk-mcp": {
4
+ "type": "stdio",
5
+ "command": "uvx",
6
+ "args": [
7
+ "--from",
8
+ "git+https://github.com/dbsanfte/topdesk-mcp",
9
+ "topdesk-mcp"
10
+ ],
11
+ }
12
+ }
13
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "python.testing.pytestArgs": [
3
+ "topdesk_mcp"
4
+ ],
5
+ "python.testing.unittestEnabled": false,
6
+ "python.testing.pytestEnabled": true
7
+ }
@@ -0,0 +1,16 @@
1
+ {
2
+ "version": "2.0.0",
3
+ "tasks": [
4
+ {
5
+ "type": "shell",
6
+ "label": "Run MCP Server",
7
+ "command": "python",
8
+ "args": [
9
+ "main.py"
10
+ ],
11
+ "group": "build",
12
+ "isBackground": false,
13
+ "problemMatcher": []
14
+ }
15
+ ]
16
+ }
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 David Sanftenberg
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,102 @@
1
+ Metadata-Version: 2.4
2
+ Name: topdesk-mcp
3
+ Version: 0.2.0
4
+ Summary: MCP server for TOPdesk API using FastMCP and TOPdeskPy SDK
5
+ License-File: LICENSE
6
+ Requires-Python: >=3.11
7
+ Requires-Dist: fastmcp
8
+ Requires-Dist: requests
9
+ Provides-Extra: dev
10
+ Requires-Dist: pytest-cov>=4.0.0; extra == 'dev'
11
+ Requires-Dist: pytest>=7.0.0; extra == 'dev'
12
+ Description-Content-Type: text/markdown
13
+
14
+ # topdesk-mcp
15
+
16
+ This project is a Model Context Protocol (MCP) server implemented in Python. It exposes the Topdesk API via the TOPdeskPy SDK.
17
+
18
+ ## Project Purpose
19
+ - Acts as an MCP server to bridge MCP clients with the Topdesk API.
20
+ - Uses the [TOPdeskPy SDK](https://github.com/TwinkelToe/TOPdeskPy) (with some modifications) for all Topdesk API interactions.
21
+
22
+ ## MCP Config JSON
23
+ ```
24
+ {
25
+ "servers": {
26
+ "topdesk-mcp": {
27
+ "type": "stdio",
28
+ "command": "uvx",
29
+ "args": [
30
+ "--from",
31
+ "git+https://github.com/dbsanfte/topdesk-mcp@master",
32
+ "topdesk-mcp"
33
+ ],
34
+ "env": {
35
+ "TOPDESK_URL": "<your topdesk URL>",
36
+ "TOPDESK_USERNAME": "<your topdesk username>",
37
+ "TOPDESK_PASSWORD": "<your topdesk api key>"
38
+ }
39
+ }
40
+ }
41
+ }
42
+ ```
43
+
44
+ ## Environment Variables
45
+ * `TOPDESK_URL`: The base URL of your Topdesk instance. e.g. `https://yourcompany.topdesk.net`
46
+ * `TOPDESK_USERNAME`: The username you generated the API token against.
47
+ * `TOPDESK_PASSWORD`: Your API token
48
+ * `TOPDESK_MCP_TRANSPORT`: (Optional) The transport to use: 'stdio', 'streamable-http', 'sse'. Defaults to 'stdio'.
49
+ * `TOPDESK_MCP_HOST`: (Optional) The host to listen on (for 'streamable-http' and 'sse'). Defaults to '0.0.0.0'.
50
+ * `TOPDESK_MCP_PORT`: (Optional) The port to listen on (for 'streamable-http' and 'sse'). Defaults to '3030'.
51
+
52
+ ## Setup for Local Development
53
+ 1. Ensure Python 3.11+ is installed.
54
+ 2. Create and activate a virtual environment:
55
+
56
+ **PowerShell:**
57
+ ```powershell
58
+ python -m venv .venv
59
+ .venv\Scripts\Activate.ps1
60
+ ```
61
+
62
+ **Bash:**
63
+ ```bash
64
+ python3 -m venv .venv
65
+ source .venv/bin/activate
66
+ ```
67
+
68
+ 3. Install dependencies:
69
+ ```
70
+ pip install uv
71
+ uv pip install -r requirements.txt
72
+ ```
73
+
74
+ 4. Run:
75
+ ```
76
+ python -m topdesk_mcp.main
77
+ ```
78
+
79
+ ### Notes:
80
+ * The server skeleton was generated using the official MCP server template.
81
+ * Contributions are welcome.
82
+
83
+ ## Package Structure
84
+ ```
85
+ topdesk_mcp/ # Directory for the MCP server package
86
+ __init__.py # Marks as a Python package
87
+ main.py # Entry point for the MCP server
88
+
89
+ _topdesk_sdk.py # TOPdeskPy SDK
90
+ _incident.py # Incidents API
91
+ _operator.py # Operator API
92
+ _person.py # Person API
93
+ _utils.py # Helper methods for Requests
94
+ ```
95
+
96
+ ## References
97
+ - [MCP Protocol Documentation](https://modelcontextprotocol.io/llms-full.txt)
98
+ - [TOPdeskPy SDK](https://github.com/TwinkelToe/TOPdeskPy)
99
+ - [FastMCP](https://github.com/jlowin/fastmcp)
100
+
101
+ ## License
102
+ MIT license.
@@ -0,0 +1,89 @@
1
+ # topdesk-mcp
2
+
3
+ This project is a Model Context Protocol (MCP) server implemented in Python. It exposes the Topdesk API via the TOPdeskPy SDK.
4
+
5
+ ## Project Purpose
6
+ - Acts as an MCP server to bridge MCP clients with the Topdesk API.
7
+ - Uses the [TOPdeskPy SDK](https://github.com/TwinkelToe/TOPdeskPy) (with some modifications) for all Topdesk API interactions.
8
+
9
+ ## MCP Config JSON
10
+ ```
11
+ {
12
+ "servers": {
13
+ "topdesk-mcp": {
14
+ "type": "stdio",
15
+ "command": "uvx",
16
+ "args": [
17
+ "--from",
18
+ "git+https://github.com/dbsanfte/topdesk-mcp@master",
19
+ "topdesk-mcp"
20
+ ],
21
+ "env": {
22
+ "TOPDESK_URL": "<your topdesk URL>",
23
+ "TOPDESK_USERNAME": "<your topdesk username>",
24
+ "TOPDESK_PASSWORD": "<your topdesk api key>"
25
+ }
26
+ }
27
+ }
28
+ }
29
+ ```
30
+
31
+ ## Environment Variables
32
+ * `TOPDESK_URL`: The base URL of your Topdesk instance. e.g. `https://yourcompany.topdesk.net`
33
+ * `TOPDESK_USERNAME`: The username you generated the API token against.
34
+ * `TOPDESK_PASSWORD`: Your API token
35
+ * `TOPDESK_MCP_TRANSPORT`: (Optional) The transport to use: 'stdio', 'streamable-http', 'sse'. Defaults to 'stdio'.
36
+ * `TOPDESK_MCP_HOST`: (Optional) The host to listen on (for 'streamable-http' and 'sse'). Defaults to '0.0.0.0'.
37
+ * `TOPDESK_MCP_PORT`: (Optional) The port to listen on (for 'streamable-http' and 'sse'). Defaults to '3030'.
38
+
39
+ ## Setup for Local Development
40
+ 1. Ensure Python 3.11+ is installed.
41
+ 2. Create and activate a virtual environment:
42
+
43
+ **PowerShell:**
44
+ ```powershell
45
+ python -m venv .venv
46
+ .venv\Scripts\Activate.ps1
47
+ ```
48
+
49
+ **Bash:**
50
+ ```bash
51
+ python3 -m venv .venv
52
+ source .venv/bin/activate
53
+ ```
54
+
55
+ 3. Install dependencies:
56
+ ```
57
+ pip install uv
58
+ uv pip install -r requirements.txt
59
+ ```
60
+
61
+ 4. Run:
62
+ ```
63
+ python -m topdesk_mcp.main
64
+ ```
65
+
66
+ ### Notes:
67
+ * The server skeleton was generated using the official MCP server template.
68
+ * Contributions are welcome.
69
+
70
+ ## Package Structure
71
+ ```
72
+ topdesk_mcp/ # Directory for the MCP server package
73
+ __init__.py # Marks as a Python package
74
+ main.py # Entry point for the MCP server
75
+
76
+ _topdesk_sdk.py # TOPdeskPy SDK
77
+ _incident.py # Incidents API
78
+ _operator.py # Operator API
79
+ _person.py # Person API
80
+ _utils.py # Helper methods for Requests
81
+ ```
82
+
83
+ ## References
84
+ - [MCP Protocol Documentation](https://modelcontextprotocol.io/llms-full.txt)
85
+ - [TOPdeskPy SDK](https://github.com/TwinkelToe/TOPdeskPy)
86
+ - [FastMCP](https://github.com/jlowin/fastmcp)
87
+
88
+ ## License
89
+ MIT license.
@@ -0,0 +1,56 @@
1
+ [project]
2
+ name = "topdesk-mcp"
3
+ version = "0.2.0"
4
+ description = "MCP server for TOPdesk API using FastMCP and TOPdeskPy SDK"
5
+ readme = "README.md"
6
+ requires-python = ">=3.11"
7
+ dependencies = [
8
+ "fastmcp",
9
+ "requests"
10
+ ]
11
+
12
+ [build-system]
13
+ requires = ["hatchling"]
14
+ build-backend = "hatchling.build"
15
+
16
+ [tool.uv]
17
+ trusted-hosts = [
18
+ "pypi.org",
19
+ "files.pythonhosted.org"
20
+ ]
21
+
22
+ [project.scripts]
23
+ topdesk-mcp = "topdesk_mcp.main:main"
24
+
25
+ [tool.pytest.ini_options]
26
+ testpaths = ["tests"]
27
+ python_files = "test_*.py"
28
+ python_classes = "Test*"
29
+ python_functions = "test_*"
30
+ filterwarnings = [
31
+ "ignore::DeprecationWarning",
32
+ "ignore::PendingDeprecationWarning",
33
+ ]
34
+ markers = [
35
+ "integration: marks tests as integration tests",
36
+ "unit: marks tests as unit tests",
37
+ ]
38
+
39
+ [project.optional-dependencies]
40
+ dev = [
41
+ "pytest>=7.0.0",
42
+ "pytest-cov>=4.0.0",
43
+ ]
44
+
45
+ [tool.coverage.run]
46
+ source = ["topdesk_mcp"]
47
+ omit = ["tests/*", "**/__init__.py"]
48
+
49
+ [tool.coverage.report]
50
+ exclude_lines = [
51
+ "pragma: no cover",
52
+ "def __repr__",
53
+ "raise NotImplementedError",
54
+ "if __name__ == .__main__.:",
55
+ "pass",
56
+ ]
@@ -0,0 +1,2 @@
1
+ # topdesk_mcp/__init__.py
2
+ # This file marks the directory as a Python package.
@@ -0,0 +1,256 @@
1
+ from topdesk_mcp import _utils
2
+ import re
3
+ import logging
4
+
5
+ class incident:
6
+
7
+ def __init__(self, topdesk_url, credpair):
8
+ self._topdesk_url = topdesk_url
9
+ self._credpair = credpair
10
+ self.utils = _utils.utils(self._topdesk_url, self._credpair)
11
+ self.action = self._action(self._topdesk_url, self._credpair)
12
+ self.request = self._request(self._topdesk_url, self._credpair)
13
+ self.timespent = self._timespent(self._topdesk_url, self._credpair)
14
+ self._logger = logging.getLogger(__name__)
15
+ self._logger.debug("Incident class initialized with URL: %s", self._topdesk_url)
16
+ self._logger.debug("Incident class initialized with credentials: %s", self._credpair)
17
+
18
+ def get(self, incident):
19
+ if self.utils.is_valid_uuid(incident):
20
+ return self.utils.handle_topdesk_response(self.utils.request_topdesk("/tas/api/incidents/id/{}".format(incident)))
21
+ else:
22
+ return self.utils.handle_topdesk_response(self.utils.request_topdesk("/tas/api/incidents/number/{}".format(incident)))
23
+
24
+ def deescalate(self, incident, reason_id=None):
25
+ if reason_id:
26
+ param = {'id': reason_id}
27
+ if self.utils.is_valid_uuid(incident):
28
+ return self.utils.handle_topdesk_response(self.utils.put_to_topdesk("/tas/api/incidents/id/{}/deescalate".format(incident), param))
29
+ else:
30
+ return self.utils.handle_topdesk_response(self.utils.put_to_topdesk("/tas/api/incidents/number/{}/deescalate".format(incident), param))
31
+
32
+ def escalate(self, incident, reason_id=None):
33
+ if reason_id:
34
+ param = {'id': reason_id}
35
+ if self.utils.is_valid_uuid(incident):
36
+ return self.utils.handle_topdesk_response(self.utils.put_to_topdesk("/tas/api/incidents/id/{}/escalate".format(incident), param))
37
+ else:
38
+ return self.utils.handle_topdesk_response(self.utils.put_to_topdesk("/tas/api/incidents/number/{}/escalate".format(incident), param))
39
+
40
+ def get_progress_trail(self, incident, inlineimages=False, non_api_attachments_url=False, page_size=100):
41
+ ext_uri= { 'inlineimages': inlineimages, 'non_api_attachments_url': non_api_attachments_url }
42
+ if self.utils.is_valid_uuid(incident):
43
+ return self.utils.handle_topdesk_response(self.utils.request_topdesk("/tas/api/incidents/id/{}/progresstrail".format(incident), page_size=page_size, extended_uri=ext_uri))
44
+ else:
45
+ return self.utils.handle_topdesk_response(self.utils.request_topdesk("/tas/api/incidents/number/{}/progresstrail".format(incident), page_size=page_size, extended_uri=ext_uri))
46
+
47
+ def patch(self, incident, **kwargs):
48
+ if self.utils.is_valid_uuid(incident):
49
+ return self.utils.handle_topdesk_response(self.utils.patch_to_topdesk("/tas/api/incidents/id/{}".format(incident), self.utils.add_id_jsonbody(**kwargs)))
50
+ else:
51
+ return self.utils.handle_topdesk_response(self.utils.patch_to_topdesk("/tas/api/incidents/number/{}".format(incident), self.utils.add_id_jsonbody(**kwargs)))
52
+
53
+ class _action:
54
+
55
+ def __init__(self, topdesk_url, credpair):
56
+ self._topdesk_url = topdesk_url
57
+ self._credpair = credpair
58
+ self.utils = _utils.utils(self._topdesk_url, self._credpair)
59
+ self._logger = logging.getLogger(__name__)
60
+ self._logger.debug("TOPdesk API action object initialised.")
61
+
62
+ def get_list(self, incident, inlineimages=False, non_api_attachments_url=False, page_size=100):
63
+ ext_uri= { 'inlineimages': inlineimages, 'non_api_attachments_url': non_api_attachments_url }
64
+ if self.utils.is_valid_uuid(incident):
65
+ return self.utils.handle_topdesk_response(self.utils.request_topdesk("/tas/api/incidents/id/{}/actions".format(incident), page_size=page_size, extended_uri=ext_uri))
66
+ else:
67
+ return self.utils.handle_topdesk_response(self.utils.request_topdesk("/tas/api/incidents/number/{}/actions".format(incident), page_size=page_size, extended_uri=ext_uri))
68
+
69
+ def get(self, incident, actions_id, inlineimages=False, non_api_attachments_url=False):
70
+ ext_uri= { 'inlineimages': inlineimages, 'non_api_attachments_url': non_api_attachments_url }
71
+ if self.utils.is_valid_uuid(incident):
72
+ return self.utils.handle_topdesk_response(self.utils.request_topdesk("/tas/api/incidents/id/{}/actions/{}".format(incident, actions_id), page_size=10, extended_uri=ext_uri))
73
+ else:
74
+ return self.utils.handle_topdesk_response(self.utils.request_topdesk("/tas/api/incidents/number/{}/actions/{}".format(incident, actions_id), page_size=10, extended_uri=ext_uri))
75
+
76
+ def delete(self, incident, actions_id):
77
+ if self.utils.is_valid_uuid(incident):
78
+ return self.utils.handle_topdesk_response(self.utils.delete_from_topdesk("/tas/api/incidents/id/{}/actions/{}".format(incident, actions_id), None))
79
+ else:
80
+ return self.utils.handle_topdesk_response(self.utils.delete_from_topdesk("/tas/api/incidents/number/{}/actions/{}".format(incident, actions_id), None))
81
+
82
+ class _request:
83
+
84
+ def __init__(self, topdesk_url, credpair):
85
+ self._topdesk_url = topdesk_url
86
+ self._credpair = credpair
87
+ self.utils = _utils.utils(self._topdesk_url, self._credpair)
88
+ self._logger = logging.getLogger(__name__)
89
+ self._logger.debug("TOPdesk API request object initialised.")
90
+
91
+ def get_list(self, incident, inlineimages=False, non_api_attachments_url=False, page_size=100):
92
+ ext_uri= { 'inlineimages': inlineimages, 'non_api_attachments_url': non_api_attachments_url }
93
+ if self.utils.is_valid_uuid(incident):
94
+ return self.utils.handle_topdesk_response(self.utils.request_topdesk("/tas/api/incidents/id/{}/requests".format(incident), page_size=page_size, extended_uri=ext_uri))
95
+ else:
96
+ return self.utils.handle_topdesk_response(self.utils.request_topdesk("/tas/api/incidents/number/{}/requests".format(incident), page_size=page_size, extended_uri=ext_uri))
97
+
98
+ def get(self, incident, request_id, inlineimages=False, non_api_attachments_url=False):
99
+ ext_uri= { 'inlineimages': inlineimages, 'non_api_attachments_url': non_api_attachments_url }
100
+ if self.utils.is_valid_uuid(incident):
101
+ return self.utils.handle_topdesk_response(self.utils.request_topdesk("/tas/api/incidents/id/{}/actions/{}".format(incident, request_id), page_size=10, extended_uri=ext_uri))
102
+ else:
103
+ return self.utils.handle_topdesk_response(self.utils.request_topdesk("/tas/api/incidents/number/{}/actions/{}".format(incident, request_id), page_size=10, extended_uri=ext_uri))
104
+
105
+ def delete(self, incident, request_id):
106
+ if self.utils.is_valid_uuid(incident):
107
+ return self.utils.handle_topdesk_response(self.utils.delete_from_topdesk("/tas/api/incidents/id/{}/actions/{}".format(incident, request_id), None))
108
+ else:
109
+ return self.utils.handle_topdesk_response(self.utils.delete_from_topdesk("/tas/api/incidents/number/{}/actions/{}".format(incident, request_id), None))
110
+
111
+ class _timespent:
112
+
113
+ def __init__(self, topdesk_url, credpair):
114
+ self._topdesk_url = topdesk_url
115
+ self._credpair = credpair
116
+ self.utils = _utils.utils(self._topdesk_url, self._credpair)
117
+ self._logger = logging.getLogger(__name__)
118
+ self._logger.debug("TOPdesk API timespent object initialised.")
119
+
120
+ def get(self, incident):
121
+ if self.utils.is_valid_uuid(incident):
122
+ return self.utils.handle_topdesk_response(self.utils.request_topdesk("/tas/api/incidents/id/{}/timespent".format(incident)))
123
+ else:
124
+ return self.utils.handle_topdesk_response(self.utils.request_topdesk("/tas/api/incidents/number/{}/timespent".format(incident)))
125
+
126
+ def register(self, incident, timespent, **kwargs):
127
+ param = {}
128
+ if kwargs:
129
+ param = kwargs
130
+ param['timespent'] = timespent
131
+ if self.utils.is_valid_uuid(incident):
132
+ return self.utils.handle_topdesk_response(self.utils.post_to_topdesk("/tas/api/incidents/id/{}/timespent".format(incident), param))
133
+ else:
134
+ return self.utils.handle_topdesk_response(self.utils.post_to_topdesk("/tas/api/incidents/number/{}/timespent".format(incident), param))
135
+
136
+ def durations(self):
137
+ return self.utils.handle_topdesk_response(self.utils.request_topdesk("/tas/api/incidents/durations"))
138
+
139
+ def statuses(self):
140
+ return self.utils.handle_topdesk_response(self.utils.request_topdesk("/tas/api/incidents/statuses"))
141
+
142
+ def deescalation_reasons(self):
143
+ return self.utils.handle_topdesk_response(self.utils.request_topdesk("/tas/api/incidents/deescalation-reasons"))
144
+
145
+ def escalation_reasons(self):
146
+ return self.utils.handle_topdesk_response(self.utils.request_topdesk("/tas/api/incidents/escalation-reasons"))
147
+
148
+ def service_windows(self):
149
+ return self.utils.handle_topdesk_response(self.utils.request_topdesk("/tas/api/incidents/slas/services"))
150
+
151
+ def call_types(self):
152
+ return self.utils.handle_topdesk_response(self.utils.request_topdesk("/tas/api/incidents/call_types"))
153
+
154
+ def closure_codes(self):
155
+ return self.utils.handle_topdesk_response(self.utils.request_topdesk("/tas/api/incidents/closure_codes"))
156
+
157
+ def entry_types(self):
158
+ return self.utils.handle_topdesk_response(self.utils.request_topdesk("/tas/api/incidents/entry_types"))
159
+
160
+ def categorys(self):
161
+ return self.utils.handle_topdesk_response(self.utils.request_topdesk("/tas/api/incidents/categories"))
162
+
163
+ def subcategorys(self):
164
+ return self.utils.handle_topdesk_response(self.utils.request_topdesk("/tas/api/incidents/subcategories"))
165
+
166
+ def impacts(self):
167
+ return self.utils.handle_topdesk_response(self.utils.request_topdesk("/tas/api/incidents/impacts"))
168
+
169
+ def priorities(self):
170
+ return self.utils.handle_topdesk_response(self.utils.request_topdesk("/tas/api/incidents/priorities"))
171
+
172
+ def urgencies(self):
173
+ return self.utils.handle_topdesk_response(self.utils.request_topdesk("/tas/api/incidents/urgencies"))
174
+
175
+ def get_id_impact(self, query):
176
+ result = self.impacts()
177
+ canidates = list()
178
+ for impact in result:
179
+ if re.match(rf"(.+)?{query}(.+)?", impact['name'], re.IGNORECASE):
180
+ canidates.append(impact['id'])
181
+
182
+ return self.utils.resolve_lookup_candidates(canidates)
183
+
184
+ def get_id_priority(self, query):
185
+ result = self.priorities()
186
+ canidates = list()
187
+ for priority in result:
188
+ if re.match(rf"(.+)?{query}(.+)?", priority['name'], re.IGNORECASE):
189
+ canidates.append(priority['id'])
190
+
191
+ return self.utils.resolve_lookup_candidates(canidates)
192
+
193
+ def get_id_urgency(self, query):
194
+ result = self.urgencies()
195
+ canidates = list()
196
+ for urgency in result:
197
+ if re.match(rf"(.+)?{query}(.+)?", urgency['name'], re.IGNORECASE):
198
+ canidates.append(urgency['id'])
199
+
200
+ return self.utils.resolve_lookup_candidates(canidates)
201
+
202
+ def get_id_entryType(self, query):
203
+ result = self.entry_types()
204
+ canidates = list()
205
+ for entryType in result:
206
+ if re.match(rf"(.+)?{query}(.+)?", entryType['name'], re.IGNORECASE):
207
+ canidates.append(entryType['id'])
208
+
209
+ return self.utils.resolve_lookup_candidates(canidates)
210
+
211
+ def get_id_callType(self, query):
212
+ result = self.call_types()
213
+ canidates = list()
214
+ for callType in result:
215
+ if re.match(rf"(.+)?{query}(.+)?", callType['name'], re.IGNORECASE):
216
+ canidates.append(callType['id'])
217
+
218
+ return self.utils.resolve_lookup_candidates(canidates)
219
+
220
+ def get_id_duration(self, query):
221
+ result = self.durations()
222
+ canidates = list()
223
+ for callType in result:
224
+ if re.match(rf"(.+)?{query}(.+)?", callType['name'], re.IGNORECASE):
225
+ canidates.append(callType['id'])
226
+
227
+ return self.utils.resolve_lookup_candidates(canidates)
228
+
229
+ def create(self, caller, **kwargs):
230
+ # Caller can be: email, uuid or unregisted user. We'll try it in that order.
231
+ create_body = kwargs
232
+ create_body['caller'] = caller
233
+ return self.utils.handle_topdesk_response(self.utils.post_to_topdesk("/tas/api/incidents/", self.utils.add_id_jsonbody(**create_body)))
234
+
235
+ def update(self, incident, **kwargs):
236
+ if self.utils.is_valid_uuid(incident):
237
+ return self.utils.handle_topdesk_response(self.utils.put_to_topdesk("/tas/api/incidents/id/{}".format(incident), self.utils.add_id_jsonbody(**kwargs)))
238
+ else:
239
+ return self.utils.handle_topdesk_response(self.utils.put_to_topdesk("/tas/api/incidents/number/{}".format(incident), self.utils.add_id_jsonbody(**kwargs)))
240
+
241
+ def archive(self, incident, reason_id=None):
242
+ if reason_id:
243
+ param = {'id': reason_id}
244
+ if self.utils.is_valid_uuid(incident):
245
+ return self.utils.handle_topdesk_response(self.utils.put_to_topdesk("/tas/api/incidents/id/{}/archive".format(incident), param))
246
+ else:
247
+ return self.utils.handle_topdesk_response(self.utils.put_to_topdesk("/tas/api/incidents/number/{}/archive".format(incident), param))
248
+
249
+ def unarchive(self, incident):
250
+ if self.utils.is_valid_uuid(incident):
251
+ return self.utils.handle_topdesk_response(self.utils.put_to_topdesk("/tas/api/incidents/id/{}/unarchive".format(incident), None))
252
+ else:
253
+ return self.utils.handle_topdesk_response(self.utils.put_to_topdesk("/tas/api/incidents/number/{}/unarchive".format(incident), None))
254
+
255
+ def get_list(self, archived=False, page_size=100, query=None, **kwargs):
256
+ return self.utils.handle_topdesk_response(self.utils.request_topdesk("/tas/api/incidents/", archived, page_size=page_size, query=query, extended_uri=kwargs))