rossum-mcp 0.4.0__py3-none-any.whl → 1.0.0__py3-none-any.whl
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.
- rossum_mcp/__init__.py +1 -1
- rossum_mcp/tools/annotations.py +11 -1
- rossum_mcp/tools/base.py +33 -0
- rossum_mcp/tools/catalog.py +8 -1
- rossum_mcp/tools/discovery.py +2 -1
- rossum_mcp/tools/email_templates.py +5 -9
- rossum_mcp/tools/hooks.py +15 -11
- rossum_mcp/tools/queues.py +25 -6
- rossum_mcp/tools/rules.py +10 -0
- rossum_mcp/tools/schemas.py +23 -7
- rossum_mcp/tools/workspaces.py +9 -1
- rossum_mcp-1.0.0.dist-info/METADATA +241 -0
- rossum_mcp-1.0.0.dist-info/RECORD +25 -0
- {rossum_mcp-0.4.0.dist-info → rossum_mcp-1.0.0.dist-info}/WHEEL +1 -1
- rossum_mcp-1.0.0.dist-info/licenses/LICENSE +21 -0
- rossum_mcp-0.4.0.dist-info/METADATA +0 -1895
- rossum_mcp-0.4.0.dist-info/RECORD +0 -24
- {rossum_mcp-0.4.0.dist-info → rossum_mcp-1.0.0.dist-info}/entry_points.txt +0 -0
- {rossum_mcp-0.4.0.dist-info → rossum_mcp-1.0.0.dist-info}/top_level.txt +0 -0
rossum_mcp/__init__.py
CHANGED
rossum_mcp/tools/annotations.py
CHANGED
|
@@ -9,7 +9,7 @@ from typing import TYPE_CHECKING, Literal
|
|
|
9
9
|
|
|
10
10
|
from rossum_api.models.annotation import Annotation
|
|
11
11
|
|
|
12
|
-
from rossum_mcp.tools.base import is_read_write_mode
|
|
12
|
+
from rossum_mcp.tools.base import delete_resource, is_read_write_mode
|
|
13
13
|
|
|
14
14
|
if TYPE_CHECKING:
|
|
15
15
|
from fastmcp import FastMCP
|
|
@@ -130,6 +130,12 @@ async def _confirm_annotation(client: AsyncRossumAPIClient, annotation_id: int)
|
|
|
130
130
|
}
|
|
131
131
|
|
|
132
132
|
|
|
133
|
+
async def _delete_annotation(client: AsyncRossumAPIClient, annotation_id: int) -> dict:
|
|
134
|
+
return await delete_resource(
|
|
135
|
+
"annotation", annotation_id, client.delete_annotation, f"Annotation {annotation_id} moved to 'deleted' status"
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
|
|
133
139
|
def register_annotation_tools(mcp: FastMCP, client: AsyncRossumAPIClient) -> None:
|
|
134
140
|
"""Register annotation-related tools with the FastMCP server."""
|
|
135
141
|
|
|
@@ -165,3 +171,7 @@ def register_annotation_tools(mcp: FastMCP, client: AsyncRossumAPIClient) -> Non
|
|
|
165
171
|
)
|
|
166
172
|
async def confirm_annotation(annotation_id: int) -> dict:
|
|
167
173
|
return await _confirm_annotation(client, annotation_id)
|
|
174
|
+
|
|
175
|
+
@mcp.tool(description="Delete an annotation. Moves to 'deleted' status (soft delete).")
|
|
176
|
+
async def delete_annotation(annotation_id: int) -> dict:
|
|
177
|
+
return await _delete_annotation(client, annotation_id)
|
rossum_mcp/tools/base.py
CHANGED
|
@@ -2,12 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
+
import logging
|
|
5
6
|
import os
|
|
6
7
|
from typing import TYPE_CHECKING
|
|
7
8
|
|
|
8
9
|
if TYPE_CHECKING:
|
|
10
|
+
from collections.abc import Awaitable, Callable
|
|
9
11
|
from typing import Any
|
|
10
12
|
|
|
13
|
+
logger = logging.getLogger(__name__)
|
|
14
|
+
|
|
11
15
|
BASE_URL = os.environ.get("ROSSUM_API_BASE_URL", "").rstrip("/")
|
|
12
16
|
MODE = os.environ.get("ROSSUM_MCP_MODE", "read-write").lower()
|
|
13
17
|
|
|
@@ -38,3 +42,32 @@ def truncate_dict_fields(data: dict[str, Any], fields: tuple[str, ...]) -> dict[
|
|
|
38
42
|
if field in result:
|
|
39
43
|
result[field] = TRUNCATED_MARKER
|
|
40
44
|
return result
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
async def delete_resource(
|
|
48
|
+
resource_type: str,
|
|
49
|
+
resource_id: int,
|
|
50
|
+
delete_fn: Callable[[int], Awaitable[None]],
|
|
51
|
+
success_message: str | None = None,
|
|
52
|
+
) -> dict:
|
|
53
|
+
"""Generic delete operation with read-only mode check.
|
|
54
|
+
|
|
55
|
+
Args:
|
|
56
|
+
resource_type: Name of the resource (e.g., "queue", "workspace")
|
|
57
|
+
resource_id: ID of the resource to delete
|
|
58
|
+
delete_fn: Async function that performs the deletion
|
|
59
|
+
success_message: Custom success message. If None, uses default format.
|
|
60
|
+
|
|
61
|
+
Returns:
|
|
62
|
+
Dict with "message" on success or "error" in read-only mode.
|
|
63
|
+
"""
|
|
64
|
+
tool_name = f"delete_{resource_type}"
|
|
65
|
+
if not is_read_write_mode():
|
|
66
|
+
return {"error": f"{tool_name} is not available in read-only mode"}
|
|
67
|
+
|
|
68
|
+
logger.debug(f"Deleting {resource_type}: {resource_type}_id={resource_id}")
|
|
69
|
+
await delete_fn(resource_id)
|
|
70
|
+
|
|
71
|
+
if success_message is None:
|
|
72
|
+
success_message = f"{resource_type.title()} {resource_id} deleted successfully"
|
|
73
|
+
return {"message": success_message}
|
rossum_mcp/tools/catalog.py
CHANGED
|
@@ -16,6 +16,7 @@ class ToolInfo:
|
|
|
16
16
|
|
|
17
17
|
name: str
|
|
18
18
|
description: str
|
|
19
|
+
destructive: bool = False
|
|
19
20
|
|
|
20
21
|
|
|
21
22
|
@dataclass
|
|
@@ -41,6 +42,7 @@ TOOL_CATALOG: dict[str, ToolCategory] = {
|
|
|
41
42
|
ToolInfo("start_annotation", "Start annotation (to_review -> reviewing)"),
|
|
42
43
|
ToolInfo("bulk_update_annotation_fields", "Bulk update annotation fields"),
|
|
43
44
|
ToolInfo("confirm_annotation", "Confirm annotation (-> confirmed)"),
|
|
45
|
+
ToolInfo("delete_annotation", "Delete annotation (soft delete)", destructive=True),
|
|
44
46
|
],
|
|
45
47
|
keywords=["annotation", "document", "upload", "extract", "confirm", "review"],
|
|
46
48
|
),
|
|
@@ -56,6 +58,7 @@ TOOL_CATALOG: dict[str, ToolCategory] = {
|
|
|
56
58
|
ToolInfo("update_queue", "Update queue settings"),
|
|
57
59
|
ToolInfo("get_queue_template_names", "List available queue templates"),
|
|
58
60
|
ToolInfo("create_queue_from_template", "Create queue from template"),
|
|
61
|
+
ToolInfo("delete_queue", "Delete queue (24h delayed)", destructive=True),
|
|
59
62
|
],
|
|
60
63
|
keywords=["queue", "inbox", "connector"],
|
|
61
64
|
),
|
|
@@ -70,6 +73,7 @@ TOOL_CATALOG: dict[str, ToolCategory] = {
|
|
|
70
73
|
ToolInfo("patch_schema", "Add/update/remove schema fields"),
|
|
71
74
|
ToolInfo("get_schema_tree_structure", "Get lightweight schema tree"),
|
|
72
75
|
ToolInfo("prune_schema_fields", "Bulk remove schema fields"),
|
|
76
|
+
ToolInfo("delete_schema", "Delete schema", destructive=True),
|
|
73
77
|
],
|
|
74
78
|
keywords=["schema", "field", "datapoint", "section", "multivalue", "tuple"],
|
|
75
79
|
),
|
|
@@ -97,6 +101,7 @@ TOOL_CATALOG: dict[str, ToolCategory] = {
|
|
|
97
101
|
ToolInfo("list_hook_logs", "View hook execution logs"),
|
|
98
102
|
ToolInfo("list_hook_templates", "List Rossum Store templates"),
|
|
99
103
|
ToolInfo("create_hook_from_template", "Create hook from template"),
|
|
104
|
+
ToolInfo("delete_hook", "Delete hook", destructive=True),
|
|
100
105
|
],
|
|
101
106
|
keywords=["hook", "extension", "webhook", "automation", "function", "serverless"],
|
|
102
107
|
),
|
|
@@ -126,7 +131,7 @@ TOOL_CATALOG: dict[str, ToolCategory] = {
|
|
|
126
131
|
ToolInfo("get_relation", "Retrieve relation details"),
|
|
127
132
|
ToolInfo("list_relations", "List annotation relations"),
|
|
128
133
|
],
|
|
129
|
-
keywords=["relation", "duplicate", "attachment"
|
|
134
|
+
keywords=["relation", "duplicate", "attachment"],
|
|
130
135
|
),
|
|
131
136
|
"rules": ToolCategory(
|
|
132
137
|
name="rules",
|
|
@@ -134,6 +139,7 @@ TOOL_CATALOG: dict[str, ToolCategory] = {
|
|
|
134
139
|
tools=[
|
|
135
140
|
ToolInfo("get_rule", "Retrieve rule details"),
|
|
136
141
|
ToolInfo("list_rules", "List validation rules"),
|
|
142
|
+
ToolInfo("delete_rule", "Delete rule", destructive=True),
|
|
137
143
|
],
|
|
138
144
|
keywords=["rule", "validation", "constraint"],
|
|
139
145
|
),
|
|
@@ -154,6 +160,7 @@ TOOL_CATALOG: dict[str, ToolCategory] = {
|
|
|
154
160
|
ToolInfo("get_workspace", "Retrieve workspace details"),
|
|
155
161
|
ToolInfo("list_workspaces", "List all workspaces"),
|
|
156
162
|
ToolInfo("create_workspace", "Create new workspace"),
|
|
163
|
+
ToolInfo("delete_workspace", "Delete workspace", destructive=True),
|
|
157
164
|
],
|
|
158
165
|
keywords=["workspace", "organization"],
|
|
159
166
|
),
|
rossum_mcp/tools/discovery.py
CHANGED
|
@@ -21,7 +21,8 @@ def register_discovery_tools(mcp: FastMCP) -> None:
|
|
|
21
21
|
@mcp.tool(
|
|
22
22
|
description="List all available tool categories with descriptions, tool names, and keywords. "
|
|
23
23
|
"Use this to discover what tools are available, then use load_tool_category to load "
|
|
24
|
-
"tools from specific categories before using them."
|
|
24
|
+
"tools from specific categories before using them. Tools with destructive=true require "
|
|
25
|
+
"explicit user request to use (delete operations)."
|
|
25
26
|
)
|
|
26
27
|
async def list_tool_categories() -> list[dict]:
|
|
27
28
|
return [
|
|
@@ -38,15 +38,11 @@ async def _list_email_templates(
|
|
|
38
38
|
if name is not None:
|
|
39
39
|
filters["name"] = name
|
|
40
40
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
templates_list
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
templates_list.append(await anext(templates_iter))
|
|
47
|
-
n += 1
|
|
48
|
-
else:
|
|
49
|
-
templates_list = [template async for template in client.list_email_templates(**filters)]
|
|
41
|
+
templates_list: list[EmailTemplate] = []
|
|
42
|
+
async for template in client.list_email_templates(**filters):
|
|
43
|
+
templates_list.append(template)
|
|
44
|
+
if first_n is not None and len(templates_list) >= first_n:
|
|
45
|
+
break
|
|
50
46
|
|
|
51
47
|
return templates_list
|
|
52
48
|
|
rossum_mcp/tools/hooks.py
CHANGED
|
@@ -8,7 +8,7 @@ from typing import TYPE_CHECKING, Annotated, Any, Literal
|
|
|
8
8
|
|
|
9
9
|
from rossum_api.models.hook import Hook, HookRunData, HookType
|
|
10
10
|
|
|
11
|
-
from rossum_mcp.tools.base import TRUNCATED_MARKER, is_read_write_mode
|
|
11
|
+
from rossum_mcp.tools.base import TRUNCATED_MARKER, delete_resource, is_read_write_mode
|
|
12
12
|
|
|
13
13
|
if TYPE_CHECKING:
|
|
14
14
|
from fastmcp import FastMCP
|
|
@@ -56,15 +56,11 @@ async def _list_hooks(
|
|
|
56
56
|
if active is not None:
|
|
57
57
|
filters["active"] = active
|
|
58
58
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
hooks_list
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
hooks_list.append(await anext(hooks_iter))
|
|
65
|
-
n += 1
|
|
66
|
-
else:
|
|
67
|
-
hooks_list = [hook async for hook in client.list_hooks(**filters)]
|
|
59
|
+
hooks_list: list[Hook] = []
|
|
60
|
+
async for hook in client.list_hooks(**filters):
|
|
61
|
+
hooks_list.append(hook)
|
|
62
|
+
if first_n is not None and len(hooks_list) >= first_n:
|
|
63
|
+
break
|
|
68
64
|
|
|
69
65
|
return hooks_list
|
|
70
66
|
|
|
@@ -238,6 +234,10 @@ async def _create_hook_from_template(
|
|
|
238
234
|
return {"error": "Hook wasn't likely created. Hook ID not available."}
|
|
239
235
|
|
|
240
236
|
|
|
237
|
+
async def _delete_hook(client: AsyncRossumAPIClient, hook_id: int) -> dict:
|
|
238
|
+
return await delete_resource("hook", hook_id, client.delete_hook)
|
|
239
|
+
|
|
240
|
+
|
|
241
241
|
def register_hook_tools(mcp: FastMCP, client: AsyncRossumAPIClient) -> None:
|
|
242
242
|
"""Register hook-related tools with the FastMCP server."""
|
|
243
243
|
|
|
@@ -256,7 +256,7 @@ def register_hook_tools(mcp: FastMCP, client: AsyncRossumAPIClient) -> None:
|
|
|
256
256
|
return await _list_hooks(client, queue_id, active, first_n)
|
|
257
257
|
|
|
258
258
|
@mcp.tool(
|
|
259
|
-
description="Create a new hook. If token_owner is provided, organization_group_admin users CANNOT be used
|
|
259
|
+
description="Create a new hook. For function hooks: 'source' in config is auto-renamed to 'function', runtime defaults to 'python3.12', timeout_s is capped at 60s. If token_owner is provided, organization_group_admin users CANNOT be used."
|
|
260
260
|
)
|
|
261
261
|
async def create_hook(
|
|
262
262
|
name: str,
|
|
@@ -341,3 +341,7 @@ def register_hook_tools(mcp: FastMCP, client: AsyncRossumAPIClient) -> None:
|
|
|
341
341
|
token_owner: str | None = None,
|
|
342
342
|
) -> Hook | dict:
|
|
343
343
|
return await _create_hook_from_template(client, name, hook_template_id, queues, events, token_owner)
|
|
344
|
+
|
|
345
|
+
@mcp.tool(description="Delete a hook.")
|
|
346
|
+
async def delete_hook(hook_id: int) -> dict:
|
|
347
|
+
return await _delete_hook(client, hook_id)
|
rossum_mcp/tools/queues.py
CHANGED
|
@@ -14,7 +14,7 @@ from rossum_api.models.engine import Engine
|
|
|
14
14
|
from rossum_api.models.queue import Queue
|
|
15
15
|
from rossum_api.models.schema import Schema
|
|
16
16
|
|
|
17
|
-
from rossum_mcp.tools.base import build_resource_url, is_read_write_mode, truncate_dict_fields
|
|
17
|
+
from rossum_mcp.tools.base import build_resource_url, delete_resource, is_read_write_mode, truncate_dict_fields
|
|
18
18
|
|
|
19
19
|
if TYPE_CHECKING:
|
|
20
20
|
from fastmcp import FastMCP
|
|
@@ -46,10 +46,15 @@ async def _get_queue(client: AsyncRossumAPIClient, queue_id: int) -> Queue:
|
|
|
46
46
|
|
|
47
47
|
|
|
48
48
|
async def _list_queues(
|
|
49
|
-
client: AsyncRossumAPIClient,
|
|
49
|
+
client: AsyncRossumAPIClient,
|
|
50
|
+
id: str | None = None,
|
|
51
|
+
workspace_id: int | None = None,
|
|
52
|
+
name: str | None = None,
|
|
50
53
|
) -> list[Queue]:
|
|
51
|
-
logger.debug(f"Listing queues: workspace_id={workspace_id}, name={name}")
|
|
54
|
+
logger.debug(f"Listing queues: id={id}, workspace_id={workspace_id}, name={name}")
|
|
52
55
|
filters: dict[str, int | str] = {}
|
|
56
|
+
if id is not None:
|
|
57
|
+
filters["id"] = id
|
|
53
58
|
if workspace_id is not None:
|
|
54
59
|
filters["workspace"] = workspace_id
|
|
55
60
|
if name is not None:
|
|
@@ -155,6 +160,12 @@ async def _update_queue(client: AsyncRossumAPIClient, queue_id: int, queue_data:
|
|
|
155
160
|
return cast("Queue", client._deserializer(Resource.Queue, updated_queue_data))
|
|
156
161
|
|
|
157
162
|
|
|
163
|
+
async def _delete_queue(client: AsyncRossumAPIClient, queue_id: int) -> dict:
|
|
164
|
+
return await delete_resource(
|
|
165
|
+
"queue", queue_id, client.delete_queue, f"Queue {queue_id} scheduled for deletion (starts after 24 hours)"
|
|
166
|
+
)
|
|
167
|
+
|
|
168
|
+
|
|
158
169
|
# Available template names for create_queue_from_template
|
|
159
170
|
QueueTemplateName = Literal[
|
|
160
171
|
"EU Demo Template",
|
|
@@ -227,9 +238,11 @@ def register_queue_tools(mcp: FastMCP, client: AsyncRossumAPIClient) -> None:
|
|
|
227
238
|
async def get_queue(queue_id: int) -> Queue:
|
|
228
239
|
return await _get_queue(client, queue_id)
|
|
229
240
|
|
|
230
|
-
@mcp.tool(description="List all queues with optional filters.")
|
|
231
|
-
async def list_queues(
|
|
232
|
-
|
|
241
|
+
@mcp.tool(description="List all queues with optional filters. id accepts comma-separated values (e.g. '1,2,3').")
|
|
242
|
+
async def list_queues(
|
|
243
|
+
id: str | None = None, workspace_id: int | None = None, name: str | None = None
|
|
244
|
+
) -> list[Queue]:
|
|
245
|
+
return await _list_queues(client, id, workspace_id, name)
|
|
233
246
|
|
|
234
247
|
@mcp.tool(description="Retrieve queue schema.")
|
|
235
248
|
async def get_queue_schema(queue_id: int) -> Schema:
|
|
@@ -272,6 +285,12 @@ def register_queue_tools(mcp: FastMCP, client: AsyncRossumAPIClient) -> None:
|
|
|
272
285
|
async def update_queue(queue_id: int, queue_data: dict) -> Queue | dict:
|
|
273
286
|
return await _update_queue(client, queue_id, queue_data)
|
|
274
287
|
|
|
288
|
+
@mcp.tool(
|
|
289
|
+
description="Delete a queue. Deletion starts after 24 hours. Also deletes all related objects (annotations, documents)."
|
|
290
|
+
)
|
|
291
|
+
async def delete_queue(queue_id: int) -> dict:
|
|
292
|
+
return await _delete_queue(client, queue_id)
|
|
293
|
+
|
|
275
294
|
@mcp.tool(description="Get available queue template names for create_queue_from_template.")
|
|
276
295
|
async def get_queue_template_names() -> list[str]:
|
|
277
296
|
return list(QUEUE_TEMPLATE_NAMES)
|
rossum_mcp/tools/rules.py
CHANGED
|
@@ -7,6 +7,8 @@ from typing import TYPE_CHECKING
|
|
|
7
7
|
|
|
8
8
|
from rossum_api.models.rule import Rule
|
|
9
9
|
|
|
10
|
+
from rossum_mcp.tools.base import delete_resource
|
|
11
|
+
|
|
10
12
|
if TYPE_CHECKING:
|
|
11
13
|
from fastmcp import FastMCP
|
|
12
14
|
from rossum_api import AsyncRossumAPIClient
|
|
@@ -39,6 +41,10 @@ async def _list_rules(
|
|
|
39
41
|
return rules_list
|
|
40
42
|
|
|
41
43
|
|
|
44
|
+
async def _delete_rule(client: AsyncRossumAPIClient, rule_id: int) -> dict:
|
|
45
|
+
return await delete_resource("rule", rule_id, client.delete_rule)
|
|
46
|
+
|
|
47
|
+
|
|
42
48
|
def register_rule_tools(mcp: FastMCP, client: AsyncRossumAPIClient) -> None:
|
|
43
49
|
"""Register rule-related tools with the FastMCP server."""
|
|
44
50
|
|
|
@@ -51,3 +57,7 @@ def register_rule_tools(mcp: FastMCP, client: AsyncRossumAPIClient) -> None:
|
|
|
51
57
|
schema_id: int | None = None, organization_id: int | None = None, enabled: bool | None = None
|
|
52
58
|
) -> list[Rule]:
|
|
53
59
|
return await _list_rules(client, schema_id, organization_id, enabled)
|
|
60
|
+
|
|
61
|
+
@mcp.tool(description="Delete a rule.")
|
|
62
|
+
async def delete_rule(rule_id: int) -> dict:
|
|
63
|
+
return await _delete_rule(client, rule_id)
|
rossum_mcp/tools/schemas.py
CHANGED
|
@@ -7,10 +7,11 @@ import logging
|
|
|
7
7
|
from dataclasses import asdict, dataclass, is_dataclass, replace
|
|
8
8
|
from typing import TYPE_CHECKING, Any, Literal
|
|
9
9
|
|
|
10
|
+
from rossum_api import APIClientError
|
|
10
11
|
from rossum_api.domain_logic.resources import Resource
|
|
11
12
|
from rossum_api.models.schema import Schema
|
|
12
13
|
|
|
13
|
-
from rossum_mcp.tools.base import TRUNCATED_MARKER, is_read_write_mode
|
|
14
|
+
from rossum_mcp.tools.base import TRUNCATED_MARKER, delete_resource, is_read_write_mode
|
|
14
15
|
|
|
15
16
|
if TYPE_CHECKING:
|
|
16
17
|
from fastmcp import FastMCP
|
|
@@ -427,9 +428,14 @@ def apply_schema_patch(
|
|
|
427
428
|
return content
|
|
428
429
|
|
|
429
430
|
|
|
430
|
-
async def _get_schema(client: AsyncRossumAPIClient, schema_id: int) -> Schema:
|
|
431
|
-
|
|
432
|
-
|
|
431
|
+
async def _get_schema(client: AsyncRossumAPIClient, schema_id: int) -> Schema | dict:
|
|
432
|
+
try:
|
|
433
|
+
schema: Schema = await client.retrieve_schema(schema_id)
|
|
434
|
+
return schema
|
|
435
|
+
except APIClientError as e:
|
|
436
|
+
if e.status_code == 404:
|
|
437
|
+
return {"error": f"Schema {schema_id} not found"}
|
|
438
|
+
raise
|
|
433
439
|
|
|
434
440
|
|
|
435
441
|
@dataclass
|
|
@@ -666,8 +672,10 @@ async def _patch_schema(
|
|
|
666
672
|
return updated_schema
|
|
667
673
|
|
|
668
674
|
|
|
669
|
-
async def _get_schema_tree_structure(client: AsyncRossumAPIClient, schema_id: int) -> list[dict]:
|
|
675
|
+
async def _get_schema_tree_structure(client: AsyncRossumAPIClient, schema_id: int) -> list[dict] | dict:
|
|
670
676
|
schema = await _get_schema(client, schema_id)
|
|
677
|
+
if isinstance(schema, dict):
|
|
678
|
+
return schema
|
|
671
679
|
content_dicts: list[dict[str, Any]] = [
|
|
672
680
|
asdict(section) if is_dataclass(section) else dict(section) # type: ignore[arg-type]
|
|
673
681
|
for section in schema.content
|
|
@@ -715,11 +723,15 @@ async def _prune_schema_fields(
|
|
|
715
723
|
return {"removed_fields": sorted(removed), "remaining_fields": sorted(remaining_ids)}
|
|
716
724
|
|
|
717
725
|
|
|
726
|
+
async def _delete_schema(client: AsyncRossumAPIClient, schema_id: int) -> dict:
|
|
727
|
+
return await delete_resource("schema", schema_id, client.delete_schema)
|
|
728
|
+
|
|
729
|
+
|
|
718
730
|
def register_schema_tools(mcp: FastMCP, client: AsyncRossumAPIClient) -> None:
|
|
719
731
|
"""Register schema-related tools with the FastMCP server."""
|
|
720
732
|
|
|
721
733
|
@mcp.tool(description="Retrieve schema details.")
|
|
722
|
-
async def get_schema(schema_id: int) -> Schema:
|
|
734
|
+
async def get_schema(schema_id: int) -> Schema | dict:
|
|
723
735
|
return await _get_schema(client, schema_id)
|
|
724
736
|
|
|
725
737
|
@mcp.tool(description="List all schemas with optional filters.")
|
|
@@ -764,7 +776,7 @@ Important: Datapoints inside a tuple MUST have an "id" field. Section-level data
|
|
|
764
776
|
return await _patch_schema(client, schema_id, operation, node_id, node_data, parent_id, position)
|
|
765
777
|
|
|
766
778
|
@mcp.tool(description="Get lightweight tree structure of schema with only ids, labels, categories, and types.")
|
|
767
|
-
async def get_schema_tree_structure(schema_id: int) -> list[dict]:
|
|
779
|
+
async def get_schema_tree_structure(schema_id: int) -> list[dict] | dict:
|
|
768
780
|
return await _get_schema_tree_structure(client, schema_id)
|
|
769
781
|
|
|
770
782
|
@mcp.tool(
|
|
@@ -782,3 +794,7 @@ Returns dict with removed_fields and remaining_fields lists. Sections cannot be
|
|
|
782
794
|
fields_to_remove: list[str] | None = None,
|
|
783
795
|
) -> dict:
|
|
784
796
|
return await _prune_schema_fields(client, schema_id, fields_to_keep, fields_to_remove)
|
|
797
|
+
|
|
798
|
+
@mcp.tool(description="Delete a schema. Fails if schema is linked to a queue or annotation (HTTP 409).")
|
|
799
|
+
async def delete_schema(schema_id: int) -> dict:
|
|
800
|
+
return await _delete_schema(client, schema_id)
|
rossum_mcp/tools/workspaces.py
CHANGED
|
@@ -7,7 +7,7 @@ from typing import TYPE_CHECKING
|
|
|
7
7
|
|
|
8
8
|
from rossum_api.models.workspace import Workspace
|
|
9
9
|
|
|
10
|
-
from rossum_mcp.tools.base import build_resource_url, is_read_write_mode
|
|
10
|
+
from rossum_mcp.tools.base import build_resource_url, delete_resource, is_read_write_mode
|
|
11
11
|
|
|
12
12
|
if TYPE_CHECKING:
|
|
13
13
|
from fastmcp import FastMCP
|
|
@@ -59,6 +59,10 @@ async def _create_workspace(
|
|
|
59
59
|
return workspace
|
|
60
60
|
|
|
61
61
|
|
|
62
|
+
async def _delete_workspace(client: AsyncRossumAPIClient, workspace_id: int) -> dict:
|
|
63
|
+
return await delete_resource("workspace", workspace_id, client.delete_workspace)
|
|
64
|
+
|
|
65
|
+
|
|
62
66
|
def register_workspace_tools(mcp: FastMCP, client: AsyncRossumAPIClient) -> None:
|
|
63
67
|
"""Register workspace-related tools with the FastMCP server."""
|
|
64
68
|
|
|
@@ -73,3 +77,7 @@ def register_workspace_tools(mcp: FastMCP, client: AsyncRossumAPIClient) -> None
|
|
|
73
77
|
@mcp.tool(description="Create a new workspace.")
|
|
74
78
|
async def create_workspace(name: str, organization_id: int, metadata: dict | None = None) -> Workspace | dict:
|
|
75
79
|
return await _create_workspace(client, name, organization_id, metadata)
|
|
80
|
+
|
|
81
|
+
@mcp.tool(description="Delete a workspace. Fails if workspace contains queues.")
|
|
82
|
+
async def delete_workspace(workspace_id: int) -> dict:
|
|
83
|
+
return await _delete_workspace(client, workspace_id)
|