rossum-mcp 1.0.0__tar.gz → 1.1.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.
- {rossum_mcp-1.0.0/rossum_mcp.egg-info → rossum_mcp-1.1.0}/PKG-INFO +27 -7
- {rossum_mcp-1.0.0 → rossum_mcp-1.1.0}/README.md +26 -6
- {rossum_mcp-1.0.0 → rossum_mcp-1.1.0}/pyproject.toml +1 -1
- {rossum_mcp-1.0.0 → rossum_mcp-1.1.0}/rossum_mcp/__init__.py +1 -1
- {rossum_mcp-1.0.0 → rossum_mcp-1.1.0}/rossum_mcp/server.py +18 -5
- {rossum_mcp-1.0.0 → rossum_mcp-1.1.0}/rossum_mcp/tools/base.py +21 -2
- {rossum_mcp-1.0.0 → rossum_mcp-1.1.0}/rossum_mcp/tools/catalog.py +29 -26
- {rossum_mcp-1.0.0 → rossum_mcp-1.1.0}/rossum_mcp/tools/discovery.py +2 -2
- rossum_mcp-1.1.0/rossum_mcp/tools/rules.py +241 -0
- {rossum_mcp-1.0.0 → rossum_mcp-1.1.0/rossum_mcp.egg-info}/PKG-INFO +27 -7
- {rossum_mcp-1.0.0 → rossum_mcp-1.1.0}/tests/test_catalog.py +27 -5
- rossum_mcp-1.0.0/rossum_mcp/tools/rules.py +0 -63
- {rossum_mcp-1.0.0 → rossum_mcp-1.1.0}/LICENSE +0 -0
- {rossum_mcp-1.0.0 → rossum_mcp-1.1.0}/rossum_mcp/logging_config.py +0 -0
- {rossum_mcp-1.0.0 → rossum_mcp-1.1.0}/rossum_mcp/py.typed +0 -0
- {rossum_mcp-1.0.0 → rossum_mcp-1.1.0}/rossum_mcp/tools/__init__.py +0 -0
- {rossum_mcp-1.0.0 → rossum_mcp-1.1.0}/rossum_mcp/tools/annotations.py +0 -0
- {rossum_mcp-1.0.0 → rossum_mcp-1.1.0}/rossum_mcp/tools/document_relations.py +0 -0
- {rossum_mcp-1.0.0 → rossum_mcp-1.1.0}/rossum_mcp/tools/email_templates.py +0 -0
- {rossum_mcp-1.0.0 → rossum_mcp-1.1.0}/rossum_mcp/tools/engines.py +0 -0
- {rossum_mcp-1.0.0 → rossum_mcp-1.1.0}/rossum_mcp/tools/hooks.py +0 -0
- {rossum_mcp-1.0.0 → rossum_mcp-1.1.0}/rossum_mcp/tools/queues.py +0 -0
- {rossum_mcp-1.0.0 → rossum_mcp-1.1.0}/rossum_mcp/tools/relations.py +0 -0
- {rossum_mcp-1.0.0 → rossum_mcp-1.1.0}/rossum_mcp/tools/schemas.py +0 -0
- {rossum_mcp-1.0.0 → rossum_mcp-1.1.0}/rossum_mcp/tools/users.py +0 -0
- {rossum_mcp-1.0.0 → rossum_mcp-1.1.0}/rossum_mcp/tools/workspaces.py +0 -0
- {rossum_mcp-1.0.0 → rossum_mcp-1.1.0}/rossum_mcp.egg-info/SOURCES.txt +0 -0
- {rossum_mcp-1.0.0 → rossum_mcp-1.1.0}/rossum_mcp.egg-info/dependency_links.txt +0 -0
- {rossum_mcp-1.0.0 → rossum_mcp-1.1.0}/rossum_mcp.egg-info/entry_points.txt +0 -0
- {rossum_mcp-1.0.0 → rossum_mcp-1.1.0}/rossum_mcp.egg-info/requires.txt +0 -0
- {rossum_mcp-1.0.0 → rossum_mcp-1.1.0}/rossum_mcp.egg-info/top_level.txt +0 -0
- {rossum_mcp-1.0.0 → rossum_mcp-1.1.0}/setup.cfg +0 -0
- {rossum_mcp-1.0.0 → rossum_mcp-1.1.0}/tests/test_logging_config.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: rossum-mcp
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.1.0
|
|
4
4
|
Summary: MCP server for AI-powered Rossum orchestration: document workflows, debug pipelines automatically, and configure intelligent document processing through natural language.
|
|
5
5
|
Author-email: "Dan Stancl (Rossum AI)" <daniel.stancl@gmail.com>
|
|
6
6
|
License: MIT
|
|
@@ -51,14 +51,14 @@ Dynamic: license-file
|
|
|
51
51
|
|
|
52
52
|
<div align="center">
|
|
53
53
|
|
|
54
|
-
**MCP server for AI-powered Rossum document processing.
|
|
54
|
+
**MCP server for AI-powered Rossum document processing. 59 tools for queues, schemas, hooks, engines, and more.**
|
|
55
55
|
|
|
56
56
|
[](https://stancld.github.io/rossum-agents/)
|
|
57
|
-
[](https://pypi.org/project/rossum-mcp/)
|
|
58
58
|
[](https://opensource.org/licenses/MIT)
|
|
59
59
|
[](https://pypi.org/project/rossum-mcp/)
|
|
60
60
|
[](https://codecov.io/gh/stancld/rossum-agents)
|
|
61
|
-
[](#available-tools)
|
|
62
62
|
|
|
63
63
|
[](https://github.com/rossumai/rossum-api)
|
|
64
64
|
[](https://modelcontextprotocol.io/)
|
|
@@ -127,9 +127,29 @@ Configure Claude Desktop (`~/Library/Application Support/Claude/claude_desktop_c
|
|
|
127
127
|
|
|
128
128
|
Set `ROSSUM_MCP_MODE=read-only` to disable all CREATE, UPDATE, and UPLOAD operations. Only GET and LIST operations will be available.
|
|
129
129
|
|
|
130
|
+
### Runtime Mode Switching
|
|
131
|
+
|
|
132
|
+
Two tools allow dynamic mode control:
|
|
133
|
+
|
|
134
|
+
| Tool | Description |
|
|
135
|
+
|------|-------------|
|
|
136
|
+
| `get_mcp_mode` | Returns current operation mode (`read-only` or `read-write`) |
|
|
137
|
+
| `set_mcp_mode` | Switches between modes at runtime |
|
|
138
|
+
|
|
139
|
+
**Use case:** Start in read-only mode for safe exploration, then switch to read-write when ready to make changes.
|
|
140
|
+
|
|
141
|
+
```
|
|
142
|
+
User: What mode are we in?
|
|
143
|
+
Assistant: [calls get_mcp_mode] → "read-only"
|
|
144
|
+
|
|
145
|
+
User: I'm ready to update the schema now.
|
|
146
|
+
Assistant: [calls set_mcp_mode("read-write")] → Mode switched to read-write
|
|
147
|
+
[calls update_schema(...)]
|
|
148
|
+
```
|
|
149
|
+
|
|
130
150
|
## Available Tools
|
|
131
151
|
|
|
132
|
-
The server provides **
|
|
152
|
+
The server provides **59 tools** organized into categories:
|
|
133
153
|
|
|
134
154
|
| Category | Tools | Description |
|
|
135
155
|
|----------|-------|-------------|
|
|
@@ -137,7 +157,7 @@ The server provides **56 tools** organized into categories:
|
|
|
137
157
|
| **Queue Management** | 9 | Create, configure, delete, and list queues |
|
|
138
158
|
| **Schema Management** | 8 | Define, modify, and delete field structures |
|
|
139
159
|
| **Engine Management** | 6 | Configure extraction and splitting engines |
|
|
140
|
-
| **Extensions & Rules** |
|
|
160
|
+
| **Extensions & Rules** | 14 | Webhooks, serverless functions, business rules |
|
|
141
161
|
| **Workspace Management** | 4 | Organize and delete workspaces |
|
|
142
162
|
| **User Management** | 3 | List users and roles |
|
|
143
163
|
| **Relations** | 4 | Annotation and document relations |
|
|
@@ -160,7 +180,7 @@ The server provides **56 tools** organized into categories:
|
|
|
160
180
|
`get_engine`, `list_engines`, `create_engine`, `update_engine`, `create_engine_field`, `get_engine_fields`
|
|
161
181
|
|
|
162
182
|
**Extensions & Rules:**
|
|
163
|
-
`get_hook`, `list_hooks`, `create_hook`, `update_hook`, `list_hook_templates`, `create_hook_from_template`, `list_hook_logs`, `delete_hook`, `get_rule`, `list_rules`, `delete_rule`
|
|
183
|
+
`get_hook`, `list_hooks`, `create_hook`, `update_hook`, `list_hook_templates`, `create_hook_from_template`, `list_hook_logs`, `delete_hook`, `get_rule`, `list_rules`, `create_rule`, `update_rule`, `patch_rule`, `delete_rule`
|
|
164
184
|
|
|
165
185
|
**Workspace Management:**
|
|
166
186
|
`get_workspace`, `list_workspaces`, `create_workspace`, `delete_workspace`
|
|
@@ -2,14 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
<div align="center">
|
|
4
4
|
|
|
5
|
-
**MCP server for AI-powered Rossum document processing.
|
|
5
|
+
**MCP server for AI-powered Rossum document processing. 59 tools for queues, schemas, hooks, engines, and more.**
|
|
6
6
|
|
|
7
7
|
[](https://stancld.github.io/rossum-agents/)
|
|
8
|
-
[](https://pypi.org/project/rossum-mcp/)
|
|
9
9
|
[](https://opensource.org/licenses/MIT)
|
|
10
10
|
[](https://pypi.org/project/rossum-mcp/)
|
|
11
11
|
[](https://codecov.io/gh/stancld/rossum-agents)
|
|
12
|
-
[](#available-tools)
|
|
13
13
|
|
|
14
14
|
[](https://github.com/rossumai/rossum-api)
|
|
15
15
|
[](https://modelcontextprotocol.io/)
|
|
@@ -78,9 +78,29 @@ Configure Claude Desktop (`~/Library/Application Support/Claude/claude_desktop_c
|
|
|
78
78
|
|
|
79
79
|
Set `ROSSUM_MCP_MODE=read-only` to disable all CREATE, UPDATE, and UPLOAD operations. Only GET and LIST operations will be available.
|
|
80
80
|
|
|
81
|
+
### Runtime Mode Switching
|
|
82
|
+
|
|
83
|
+
Two tools allow dynamic mode control:
|
|
84
|
+
|
|
85
|
+
| Tool | Description |
|
|
86
|
+
|------|-------------|
|
|
87
|
+
| `get_mcp_mode` | Returns current operation mode (`read-only` or `read-write`) |
|
|
88
|
+
| `set_mcp_mode` | Switches between modes at runtime |
|
|
89
|
+
|
|
90
|
+
**Use case:** Start in read-only mode for safe exploration, then switch to read-write when ready to make changes.
|
|
91
|
+
|
|
92
|
+
```
|
|
93
|
+
User: What mode are we in?
|
|
94
|
+
Assistant: [calls get_mcp_mode] → "read-only"
|
|
95
|
+
|
|
96
|
+
User: I'm ready to update the schema now.
|
|
97
|
+
Assistant: [calls set_mcp_mode("read-write")] → Mode switched to read-write
|
|
98
|
+
[calls update_schema(...)]
|
|
99
|
+
```
|
|
100
|
+
|
|
81
101
|
## Available Tools
|
|
82
102
|
|
|
83
|
-
The server provides **
|
|
103
|
+
The server provides **59 tools** organized into categories:
|
|
84
104
|
|
|
85
105
|
| Category | Tools | Description |
|
|
86
106
|
|----------|-------|-------------|
|
|
@@ -88,7 +108,7 @@ The server provides **56 tools** organized into categories:
|
|
|
88
108
|
| **Queue Management** | 9 | Create, configure, delete, and list queues |
|
|
89
109
|
| **Schema Management** | 8 | Define, modify, and delete field structures |
|
|
90
110
|
| **Engine Management** | 6 | Configure extraction and splitting engines |
|
|
91
|
-
| **Extensions & Rules** |
|
|
111
|
+
| **Extensions & Rules** | 14 | Webhooks, serverless functions, business rules |
|
|
92
112
|
| **Workspace Management** | 4 | Organize and delete workspaces |
|
|
93
113
|
| **User Management** | 3 | List users and roles |
|
|
94
114
|
| **Relations** | 4 | Annotation and document relations |
|
|
@@ -111,7 +131,7 @@ The server provides **56 tools** organized into categories:
|
|
|
111
131
|
`get_engine`, `list_engines`, `create_engine`, `update_engine`, `create_engine_field`, `get_engine_fields`
|
|
112
132
|
|
|
113
133
|
**Extensions & Rules:**
|
|
114
|
-
`get_hook`, `list_hooks`, `create_hook`, `update_hook`, `list_hook_templates`, `create_hook_from_template`, `list_hook_logs`, `delete_hook`, `get_rule`, `list_rules`, `delete_rule`
|
|
134
|
+
`get_hook`, `list_hooks`, `create_hook`, `update_hook`, `list_hook_templates`, `create_hook_from_template`, `list_hook_logs`, `delete_hook`, `get_rule`, `list_rules`, `create_rule`, `update_rule`, `patch_rule`, `delete_rule`
|
|
115
135
|
|
|
116
136
|
**Workspace Management:**
|
|
117
137
|
`get_workspace`, `list_workspaces`, `create_workspace`, `delete_workspace`
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "rossum-mcp"
|
|
7
|
-
version = "1.
|
|
7
|
+
version = "1.1.0"
|
|
8
8
|
description = "MCP server for AI-powered Rossum orchestration: document workflows, debug pipelines automatically, and configure intelligent document processing through natural language."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.12"
|
|
@@ -29,6 +29,7 @@ from rossum_mcp.tools import (
|
|
|
29
29
|
register_user_tools,
|
|
30
30
|
register_workspace_tools,
|
|
31
31
|
)
|
|
32
|
+
from rossum_mcp.tools.base import get_mcp_mode, set_mcp_mode
|
|
32
33
|
|
|
33
34
|
setup_logging(app_name="rossum-mcp-server", log_level="DEBUG", use_console=False)
|
|
34
35
|
|
|
@@ -36,12 +37,8 @@ logger = logging.getLogger(__name__)
|
|
|
36
37
|
|
|
37
38
|
BASE_URL = os.environ["ROSSUM_API_BASE_URL"].rstrip("/")
|
|
38
39
|
API_TOKEN = os.environ["ROSSUM_API_TOKEN"]
|
|
39
|
-
MODE = os.environ.get("ROSSUM_MCP_MODE", "read-write").lower()
|
|
40
40
|
|
|
41
|
-
|
|
42
|
-
raise ValueError(f"Invalid ROSSUM_MCP_MODE: {MODE}. Must be 'read-only' or 'read-write'")
|
|
43
|
-
|
|
44
|
-
logger.info(f"Rossum MCP Server starting in {MODE} mode")
|
|
41
|
+
logger.info(f"Rossum MCP Server starting in {get_mcp_mode()} mode")
|
|
45
42
|
|
|
46
43
|
mcp = FastMCP("rossum-mcp-server")
|
|
47
44
|
client = AsyncRossumAPIClient(base_url=BASE_URL, credentials=Token(token=API_TOKEN))
|
|
@@ -60,6 +57,22 @@ register_user_tools(mcp, client)
|
|
|
60
57
|
register_workspace_tools(mcp, client)
|
|
61
58
|
|
|
62
59
|
|
|
60
|
+
@mcp.tool(description="Get the current MCP operation mode (read-only or read-write).")
|
|
61
|
+
async def get_mcp_mode_tool() -> dict:
|
|
62
|
+
return {"mode": get_mcp_mode()}
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
@mcp.tool(
|
|
66
|
+
description="Set the MCP operation mode. Use 'read-only' to disable write operations, 'read-write' to enable them."
|
|
67
|
+
)
|
|
68
|
+
async def set_mcp_mode_tool(mode: str) -> dict:
|
|
69
|
+
try:
|
|
70
|
+
set_mcp_mode(mode)
|
|
71
|
+
return {"message": f"MCP mode set to '{get_mcp_mode()}'"}
|
|
72
|
+
except ValueError as e:
|
|
73
|
+
return {"error": str(e)}
|
|
74
|
+
|
|
75
|
+
|
|
63
76
|
def main() -> None:
|
|
64
77
|
"""Main entry point for console script."""
|
|
65
78
|
mcp.run()
|
|
@@ -13,11 +13,30 @@ if TYPE_CHECKING:
|
|
|
13
13
|
logger = logging.getLogger(__name__)
|
|
14
14
|
|
|
15
15
|
BASE_URL = os.environ.get("ROSSUM_API_BASE_URL", "").rstrip("/")
|
|
16
|
-
MODE = os.environ.get("ROSSUM_MCP_MODE", "read-write").lower()
|
|
17
16
|
|
|
18
17
|
# Marker used to indicate omitted fields in list responses
|
|
19
18
|
TRUNCATED_MARKER = "<omitted>"
|
|
20
19
|
|
|
20
|
+
VALID_MODES = ("read-only", "read-write")
|
|
21
|
+
|
|
22
|
+
_mcp_mode = os.environ.get("ROSSUM_MCP_MODE", "read-write").lower()
|
|
23
|
+
if _mcp_mode not in VALID_MODES:
|
|
24
|
+
raise ValueError(f"Invalid ROSSUM_MCP_MODE: {_mcp_mode}. Must be one of: {VALID_MODES}")
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def get_mcp_mode() -> str:
|
|
28
|
+
"""Return the current MCP mode."""
|
|
29
|
+
return _mcp_mode
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def set_mcp_mode(mode: str) -> None:
|
|
33
|
+
"""Set the MCP mode (case-insensitive)."""
|
|
34
|
+
global _mcp_mode
|
|
35
|
+
normalized = mode.lower()
|
|
36
|
+
if normalized not in VALID_MODES:
|
|
37
|
+
raise ValueError(f"Invalid mode '{mode}'. Must be one of: {VALID_MODES}")
|
|
38
|
+
_mcp_mode = normalized
|
|
39
|
+
|
|
21
40
|
|
|
22
41
|
def build_resource_url(resource_type: str, resource_id: int) -> str:
|
|
23
42
|
"""Build a full URL for a Rossum API resource."""
|
|
@@ -26,7 +45,7 @@ def build_resource_url(resource_type: str, resource_id: int) -> str:
|
|
|
26
45
|
|
|
27
46
|
def is_read_write_mode() -> bool:
|
|
28
47
|
"""Check if server is in read-write mode."""
|
|
29
|
-
return
|
|
48
|
+
return _mcp_mode == "read-write"
|
|
30
49
|
|
|
31
50
|
|
|
32
51
|
def truncate_dict_fields(data: dict[str, Any], fields: tuple[str, ...]) -> dict[str, Any]:
|
|
@@ -16,7 +16,7 @@ class ToolInfo:
|
|
|
16
16
|
|
|
17
17
|
name: str
|
|
18
18
|
description: str
|
|
19
|
-
|
|
19
|
+
read_only: bool = True
|
|
20
20
|
|
|
21
21
|
|
|
22
22
|
@dataclass
|
|
@@ -36,13 +36,13 @@ TOOL_CATALOG: dict[str, ToolCategory] = {
|
|
|
36
36
|
name="annotations",
|
|
37
37
|
description="Document processing: upload, retrieve, update, and confirm annotations",
|
|
38
38
|
tools=[
|
|
39
|
-
ToolInfo("upload_document", "Upload document to queue"),
|
|
39
|
+
ToolInfo("upload_document", "Upload document to queue", read_only=False),
|
|
40
40
|
ToolInfo("get_annotation", "Retrieve annotation with extracted data"),
|
|
41
41
|
ToolInfo("list_annotations", "List annotations for a queue"),
|
|
42
|
-
ToolInfo("start_annotation", "Start annotation (to_review -> reviewing)"),
|
|
43
|
-
ToolInfo("bulk_update_annotation_fields", "Bulk update annotation fields"),
|
|
44
|
-
ToolInfo("confirm_annotation", "Confirm annotation (-> confirmed)"),
|
|
45
|
-
ToolInfo("delete_annotation", "Delete annotation (soft delete)",
|
|
42
|
+
ToolInfo("start_annotation", "Start annotation (to_review -> reviewing)", read_only=False),
|
|
43
|
+
ToolInfo("bulk_update_annotation_fields", "Bulk update annotation fields", read_only=False),
|
|
44
|
+
ToolInfo("confirm_annotation", "Confirm annotation (-> confirmed)", read_only=False),
|
|
45
|
+
ToolInfo("delete_annotation", "Delete annotation (soft delete)", read_only=False),
|
|
46
46
|
],
|
|
47
47
|
keywords=["annotation", "document", "upload", "extract", "confirm", "review"],
|
|
48
48
|
),
|
|
@@ -54,11 +54,11 @@ TOOL_CATALOG: dict[str, ToolCategory] = {
|
|
|
54
54
|
ToolInfo("list_queues", "List all queues"),
|
|
55
55
|
ToolInfo("get_queue_schema", "Get queue's schema"),
|
|
56
56
|
ToolInfo("get_queue_engine", "Get queue's AI engine"),
|
|
57
|
-
ToolInfo("create_queue", "Create a queue"),
|
|
58
|
-
ToolInfo("update_queue", "Update queue settings"),
|
|
57
|
+
ToolInfo("create_queue", "Create a queue", read_only=False),
|
|
58
|
+
ToolInfo("update_queue", "Update queue settings", read_only=False),
|
|
59
59
|
ToolInfo("get_queue_template_names", "List available queue templates"),
|
|
60
|
-
ToolInfo("create_queue_from_template", "Create queue from template"),
|
|
61
|
-
ToolInfo("delete_queue", "Delete queue (24h delayed)",
|
|
60
|
+
ToolInfo("create_queue_from_template", "Create queue from template", read_only=False),
|
|
61
|
+
ToolInfo("delete_queue", "Delete queue (24h delayed)", read_only=False),
|
|
62
62
|
],
|
|
63
63
|
keywords=["queue", "inbox", "connector"],
|
|
64
64
|
),
|
|
@@ -68,12 +68,12 @@ TOOL_CATALOG: dict[str, ToolCategory] = {
|
|
|
68
68
|
tools=[
|
|
69
69
|
ToolInfo("get_schema", "Retrieve schema details"),
|
|
70
70
|
ToolInfo("list_schemas", "List all schemas"),
|
|
71
|
-
ToolInfo("update_schema", "Update schema"),
|
|
72
|
-
ToolInfo("create_schema", "Create new schema"),
|
|
73
|
-
ToolInfo("patch_schema", "Add/update/remove schema fields"),
|
|
71
|
+
ToolInfo("update_schema", "Update schema", read_only=False),
|
|
72
|
+
ToolInfo("create_schema", "Create new schema", read_only=False),
|
|
73
|
+
ToolInfo("patch_schema", "Add/update/remove schema fields", read_only=False),
|
|
74
74
|
ToolInfo("get_schema_tree_structure", "Get lightweight schema tree"),
|
|
75
|
-
ToolInfo("prune_schema_fields", "Bulk remove schema fields"),
|
|
76
|
-
ToolInfo("delete_schema", "Delete schema",
|
|
75
|
+
ToolInfo("prune_schema_fields", "Bulk remove schema fields", read_only=False),
|
|
76
|
+
ToolInfo("delete_schema", "Delete schema", read_only=False),
|
|
77
77
|
],
|
|
78
78
|
keywords=["schema", "field", "datapoint", "section", "multivalue", "tuple"],
|
|
79
79
|
),
|
|
@@ -83,9 +83,9 @@ TOOL_CATALOG: dict[str, ToolCategory] = {
|
|
|
83
83
|
tools=[
|
|
84
84
|
ToolInfo("get_engine", "Retrieve engine details"),
|
|
85
85
|
ToolInfo("list_engines", "List all engines"),
|
|
86
|
-
ToolInfo("update_engine", "Update engine settings"),
|
|
87
|
-
ToolInfo("create_engine", "Create new engine"),
|
|
88
|
-
ToolInfo("create_engine_field", "Create engine field mapping"),
|
|
86
|
+
ToolInfo("update_engine", "Update engine settings", read_only=False),
|
|
87
|
+
ToolInfo("create_engine", "Create new engine", read_only=False),
|
|
88
|
+
ToolInfo("create_engine_field", "Create engine field mapping", read_only=False),
|
|
89
89
|
ToolInfo("get_engine_fields", "List engine fields"),
|
|
90
90
|
],
|
|
91
91
|
keywords=["engine", "ai", "extractor", "splitter", "training"],
|
|
@@ -96,12 +96,12 @@ TOOL_CATALOG: dict[str, ToolCategory] = {
|
|
|
96
96
|
tools=[
|
|
97
97
|
ToolInfo("get_hook", "Retrieve hook details with code"),
|
|
98
98
|
ToolInfo("list_hooks", "List all hooks for a queue"),
|
|
99
|
-
ToolInfo("create_hook", "Create new hook"),
|
|
100
|
-
ToolInfo("update_hook", "Update hook configuration"),
|
|
99
|
+
ToolInfo("create_hook", "Create new hook", read_only=False),
|
|
100
|
+
ToolInfo("update_hook", "Update hook configuration", read_only=False),
|
|
101
101
|
ToolInfo("list_hook_logs", "View hook execution logs"),
|
|
102
102
|
ToolInfo("list_hook_templates", "List Rossum Store templates"),
|
|
103
|
-
ToolInfo("create_hook_from_template", "Create hook from template"),
|
|
104
|
-
ToolInfo("delete_hook", "Delete hook",
|
|
103
|
+
ToolInfo("create_hook_from_template", "Create hook from template", read_only=False),
|
|
104
|
+
ToolInfo("delete_hook", "Delete hook", read_only=False),
|
|
105
105
|
],
|
|
106
106
|
keywords=["hook", "extension", "webhook", "automation", "function", "serverless"],
|
|
107
107
|
),
|
|
@@ -111,7 +111,7 @@ TOOL_CATALOG: dict[str, ToolCategory] = {
|
|
|
111
111
|
tools=[
|
|
112
112
|
ToolInfo("get_email_template", "Retrieve email template"),
|
|
113
113
|
ToolInfo("list_email_templates", "List email templates"),
|
|
114
|
-
ToolInfo("create_email_template", "Create email template"),
|
|
114
|
+
ToolInfo("create_email_template", "Create email template", read_only=False),
|
|
115
115
|
],
|
|
116
116
|
keywords=["email", "template", "notification", "rejection"],
|
|
117
117
|
),
|
|
@@ -139,7 +139,10 @@ TOOL_CATALOG: dict[str, ToolCategory] = {
|
|
|
139
139
|
tools=[
|
|
140
140
|
ToolInfo("get_rule", "Retrieve rule details"),
|
|
141
141
|
ToolInfo("list_rules", "List validation rules"),
|
|
142
|
-
ToolInfo("
|
|
142
|
+
ToolInfo("create_rule", "Create validation rule", read_only=False),
|
|
143
|
+
ToolInfo("update_rule", "Full update rule (PUT)", read_only=False),
|
|
144
|
+
ToolInfo("patch_rule", "Partial update rule (PATCH)", read_only=False),
|
|
145
|
+
ToolInfo("delete_rule", "Delete rule", read_only=False),
|
|
143
146
|
],
|
|
144
147
|
keywords=["rule", "validation", "constraint"],
|
|
145
148
|
),
|
|
@@ -159,8 +162,8 @@ TOOL_CATALOG: dict[str, ToolCategory] = {
|
|
|
159
162
|
tools=[
|
|
160
163
|
ToolInfo("get_workspace", "Retrieve workspace details"),
|
|
161
164
|
ToolInfo("list_workspaces", "List all workspaces"),
|
|
162
|
-
ToolInfo("create_workspace", "Create new workspace"),
|
|
163
|
-
ToolInfo("delete_workspace", "Delete workspace",
|
|
165
|
+
ToolInfo("create_workspace", "Create new workspace", read_only=False),
|
|
166
|
+
ToolInfo("delete_workspace", "Delete workspace", read_only=False),
|
|
164
167
|
],
|
|
165
168
|
keywords=["workspace", "organization"],
|
|
166
169
|
),
|
|
@@ -21,8 +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. Tools with
|
|
25
|
-
"
|
|
24
|
+
"tools from specific categories before using them. Tools with read_only=false are write "
|
|
25
|
+
"operations (create, update, delete)."
|
|
26
26
|
)
|
|
27
27
|
async def list_tool_categories() -> list[dict]:
|
|
28
28
|
return [
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
"""Rule tools for Rossum MCP Server."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import logging
|
|
6
|
+
from typing import TYPE_CHECKING, Literal, TypedDict
|
|
7
|
+
|
|
8
|
+
from rossum_api.domain_logic.resources import Resource
|
|
9
|
+
from rossum_api.models.rule import Rule
|
|
10
|
+
|
|
11
|
+
from rossum_mcp.tools.base import build_resource_url, delete_resource, is_read_write_mode
|
|
12
|
+
|
|
13
|
+
if TYPE_CHECKING:
|
|
14
|
+
from fastmcp import FastMCP
|
|
15
|
+
from rossum_api import AsyncRossumAPIClient
|
|
16
|
+
|
|
17
|
+
logger = logging.getLogger(__name__)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
RuleActionType = Literal[
|
|
21
|
+
"show_message",
|
|
22
|
+
"add_automation_blocker",
|
|
23
|
+
"add_validation_source",
|
|
24
|
+
"change_queue",
|
|
25
|
+
"send_email",
|
|
26
|
+
"hide_field",
|
|
27
|
+
"show_field",
|
|
28
|
+
"show_hide_field",
|
|
29
|
+
"change_status",
|
|
30
|
+
"add_label",
|
|
31
|
+
"remove_label",
|
|
32
|
+
"custom",
|
|
33
|
+
]
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class RuleActionPayload(TypedDict, total=False):
|
|
37
|
+
"""Payload for rule actions. Fields depend on action type."""
|
|
38
|
+
|
|
39
|
+
type: Literal["info", "warning", "error"] # for show_message
|
|
40
|
+
content: str # message content or template
|
|
41
|
+
schema_id: str # target field schema_id
|
|
42
|
+
queue_url: str # for change_queue
|
|
43
|
+
status: str # for change_status
|
|
44
|
+
label: str # for add_label/remove_label
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class RuleAction(TypedDict):
|
|
48
|
+
"""Rule action definition."""
|
|
49
|
+
|
|
50
|
+
id: str # unique action identifier
|
|
51
|
+
type: RuleActionType
|
|
52
|
+
event: Literal["validation"]
|
|
53
|
+
payload: RuleActionPayload
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
async def _get_rule(client: AsyncRossumAPIClient, rule_id: int) -> Rule:
|
|
57
|
+
logger.debug(f"Retrieving rule: rule_id={rule_id}")
|
|
58
|
+
rule: Rule = await client.retrieve_rule(rule_id)
|
|
59
|
+
return rule
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
async def _list_rules(
|
|
63
|
+
client: AsyncRossumAPIClient,
|
|
64
|
+
schema_id: int | None = None,
|
|
65
|
+
organization_id: int | None = None,
|
|
66
|
+
enabled: bool | None = None,
|
|
67
|
+
) -> list[Rule]:
|
|
68
|
+
logger.debug(f"Listing rules: schema_id={schema_id}, organization_id={organization_id}, enabled={enabled}")
|
|
69
|
+
filters: dict = {}
|
|
70
|
+
if schema_id is not None:
|
|
71
|
+
filters["schema"] = schema_id
|
|
72
|
+
if organization_id is not None:
|
|
73
|
+
filters["organization"] = organization_id
|
|
74
|
+
if enabled is not None:
|
|
75
|
+
filters["enabled"] = enabled
|
|
76
|
+
|
|
77
|
+
rules_list: list[Rule] = [rule async for rule in client.list_rules(**filters)]
|
|
78
|
+
return rules_list
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
async def _create_rule(
|
|
82
|
+
client: AsyncRossumAPIClient,
|
|
83
|
+
name: str,
|
|
84
|
+
schema_id: int,
|
|
85
|
+
trigger_condition: str,
|
|
86
|
+
actions: list[RuleAction],
|
|
87
|
+
enabled: bool = True,
|
|
88
|
+
queue_ids: list[int] | None = None,
|
|
89
|
+
) -> Rule | dict:
|
|
90
|
+
if not is_read_write_mode():
|
|
91
|
+
return {"error": "create_rule is not available in read-only mode"}
|
|
92
|
+
|
|
93
|
+
schema_url = build_resource_url("schemas", schema_id)
|
|
94
|
+
logger.info(f"Creating rule: name={name}, schema_id={schema_id}, enabled={enabled}")
|
|
95
|
+
|
|
96
|
+
rule_data: dict = {
|
|
97
|
+
"name": name,
|
|
98
|
+
"schema": schema_url,
|
|
99
|
+
"trigger_condition": trigger_condition,
|
|
100
|
+
"actions": actions,
|
|
101
|
+
"enabled": enabled,
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
if queue_ids is not None:
|
|
105
|
+
rule_data["queues"] = [build_resource_url("queues", qid) for qid in queue_ids]
|
|
106
|
+
|
|
107
|
+
logger.debug(f"Rule creation payload: {rule_data}")
|
|
108
|
+
rule: Rule = await client.create_new_rule(rule_data)
|
|
109
|
+
logger.info(f"Successfully created rule: id={rule.id}, name={rule.name}")
|
|
110
|
+
return rule
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
async def _update_rule(
|
|
114
|
+
client: AsyncRossumAPIClient,
|
|
115
|
+
rule_id: int,
|
|
116
|
+
name: str,
|
|
117
|
+
trigger_condition: str,
|
|
118
|
+
actions: list[RuleAction],
|
|
119
|
+
enabled: bool,
|
|
120
|
+
queue_ids: list[int] | None = None,
|
|
121
|
+
) -> Rule | dict:
|
|
122
|
+
"""Full update (PUT) - all fields required."""
|
|
123
|
+
if not is_read_write_mode():
|
|
124
|
+
return {"error": "update_rule is not available in read-only mode"}
|
|
125
|
+
|
|
126
|
+
logger.info(f"Updating rule: rule_id={rule_id}, name={name}")
|
|
127
|
+
existing_rule: Rule = await client.retrieve_rule(rule_id)
|
|
128
|
+
|
|
129
|
+
rule_data: dict = {
|
|
130
|
+
"name": name,
|
|
131
|
+
"schema": existing_rule.schema,
|
|
132
|
+
"trigger_condition": trigger_condition,
|
|
133
|
+
"actions": actions,
|
|
134
|
+
"enabled": enabled,
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if queue_ids is not None:
|
|
138
|
+
rule_data["queues"] = [build_resource_url("queues", qid) for qid in queue_ids]
|
|
139
|
+
|
|
140
|
+
logger.debug(f"Rule update payload: {rule_data}")
|
|
141
|
+
await client._http_client.update(Resource.Rule, rule_id, rule_data)
|
|
142
|
+
updated_rule: Rule = await client.retrieve_rule(rule_id)
|
|
143
|
+
logger.info(f"Successfully updated rule: id={updated_rule.id}")
|
|
144
|
+
return updated_rule
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
async def _patch_rule(
|
|
148
|
+
client: AsyncRossumAPIClient,
|
|
149
|
+
rule_id: int,
|
|
150
|
+
name: str | None = None,
|
|
151
|
+
trigger_condition: str | None = None,
|
|
152
|
+
actions: list[RuleAction] | None = None,
|
|
153
|
+
enabled: bool | None = None,
|
|
154
|
+
queue_ids: list[int] | None = None,
|
|
155
|
+
) -> Rule | dict:
|
|
156
|
+
"""Partial update (PATCH) - only provided fields are updated."""
|
|
157
|
+
if not is_read_write_mode():
|
|
158
|
+
return {"error": "patch_rule is not available in read-only mode"}
|
|
159
|
+
|
|
160
|
+
logger.info(f"Patching rule: rule_id={rule_id}")
|
|
161
|
+
|
|
162
|
+
patch_data: dict = {}
|
|
163
|
+
if name is not None:
|
|
164
|
+
patch_data["name"] = name
|
|
165
|
+
if trigger_condition is not None:
|
|
166
|
+
patch_data["trigger_condition"] = trigger_condition
|
|
167
|
+
if actions is not None:
|
|
168
|
+
patch_data["actions"] = actions
|
|
169
|
+
if enabled is not None:
|
|
170
|
+
patch_data["enabled"] = enabled
|
|
171
|
+
if queue_ids is not None:
|
|
172
|
+
patch_data["queues"] = [build_resource_url("queues", qid) for qid in queue_ids]
|
|
173
|
+
|
|
174
|
+
if not patch_data:
|
|
175
|
+
return {"error": "No fields provided to update"}
|
|
176
|
+
|
|
177
|
+
logger.debug(f"Rule patch payload: {patch_data}")
|
|
178
|
+
updated_rule: Rule = await client.update_part_rule(rule_id, patch_data)
|
|
179
|
+
logger.info(f"Successfully patched rule: id={updated_rule.id}")
|
|
180
|
+
return updated_rule
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
async def _delete_rule(client: AsyncRossumAPIClient, rule_id: int) -> dict:
|
|
184
|
+
return await delete_resource("rule", rule_id, client.delete_rule)
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
def register_rule_tools(mcp: FastMCP, client: AsyncRossumAPIClient) -> None:
|
|
188
|
+
"""Register rule-related tools with the FastMCP server."""
|
|
189
|
+
|
|
190
|
+
@mcp.tool(description="Retrieve rule details.")
|
|
191
|
+
async def get_rule(rule_id: int) -> Rule:
|
|
192
|
+
return await _get_rule(client, rule_id)
|
|
193
|
+
|
|
194
|
+
@mcp.tool(description="List all rules.")
|
|
195
|
+
async def list_rules(
|
|
196
|
+
schema_id: int | None = None, organization_id: int | None = None, enabled: bool | None = None
|
|
197
|
+
) -> list[Rule]:
|
|
198
|
+
return await _list_rules(client, schema_id, organization_id, enabled)
|
|
199
|
+
|
|
200
|
+
@mcp.tool(
|
|
201
|
+
description="Create a new rule. Rules automate field operations based on trigger conditions (TxScript formulas like 'field.amount > 1000'). Actions require: id (unique str), type (show_message|hide_field|show_field|change_status|custom|etc), event (validation), payload (dict with type, content, schema_id for show_message). queue_ids limits rule to specific queues."
|
|
202
|
+
)
|
|
203
|
+
async def create_rule(
|
|
204
|
+
name: str,
|
|
205
|
+
schema_id: int,
|
|
206
|
+
trigger_condition: str,
|
|
207
|
+
actions: list[RuleAction],
|
|
208
|
+
enabled: bool = True,
|
|
209
|
+
queue_ids: list[int] | None = None,
|
|
210
|
+
) -> Rule | dict:
|
|
211
|
+
return await _create_rule(client, name, schema_id, trigger_condition, actions, enabled, queue_ids)
|
|
212
|
+
|
|
213
|
+
@mcp.tool(
|
|
214
|
+
description="Full update of a rule (PUT). All fields required. Use patch_rule for partial updates. queue_ids limits rule to specific queues."
|
|
215
|
+
)
|
|
216
|
+
async def update_rule(
|
|
217
|
+
rule_id: int,
|
|
218
|
+
name: str,
|
|
219
|
+
trigger_condition: str,
|
|
220
|
+
actions: list[RuleAction],
|
|
221
|
+
enabled: bool,
|
|
222
|
+
queue_ids: list[int] | None = None,
|
|
223
|
+
) -> Rule | dict:
|
|
224
|
+
return await _update_rule(client, rule_id, name, trigger_condition, actions, enabled, queue_ids)
|
|
225
|
+
|
|
226
|
+
@mcp.tool(
|
|
227
|
+
description="Partial update of a rule (PATCH). Only provided fields are updated. queue_ids limits rule to specific queues (empty list removes all)."
|
|
228
|
+
)
|
|
229
|
+
async def patch_rule(
|
|
230
|
+
rule_id: int,
|
|
231
|
+
name: str | None = None,
|
|
232
|
+
trigger_condition: str | None = None,
|
|
233
|
+
actions: list[RuleAction] | None = None,
|
|
234
|
+
enabled: bool | None = None,
|
|
235
|
+
queue_ids: list[int] | None = None,
|
|
236
|
+
) -> Rule | dict:
|
|
237
|
+
return await _patch_rule(client, rule_id, name, trigger_condition, actions, enabled, queue_ids)
|
|
238
|
+
|
|
239
|
+
@mcp.tool(description="Delete a rule.")
|
|
240
|
+
async def delete_rule(rule_id: int) -> dict:
|
|
241
|
+
return await _delete_rule(client, rule_id)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: rossum-mcp
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.1.0
|
|
4
4
|
Summary: MCP server for AI-powered Rossum orchestration: document workflows, debug pipelines automatically, and configure intelligent document processing through natural language.
|
|
5
5
|
Author-email: "Dan Stancl (Rossum AI)" <daniel.stancl@gmail.com>
|
|
6
6
|
License: MIT
|
|
@@ -51,14 +51,14 @@ Dynamic: license-file
|
|
|
51
51
|
|
|
52
52
|
<div align="center">
|
|
53
53
|
|
|
54
|
-
**MCP server for AI-powered Rossum document processing.
|
|
54
|
+
**MCP server for AI-powered Rossum document processing. 59 tools for queues, schemas, hooks, engines, and more.**
|
|
55
55
|
|
|
56
56
|
[](https://stancld.github.io/rossum-agents/)
|
|
57
|
-
[](https://pypi.org/project/rossum-mcp/)
|
|
58
58
|
[](https://opensource.org/licenses/MIT)
|
|
59
59
|
[](https://pypi.org/project/rossum-mcp/)
|
|
60
60
|
[](https://codecov.io/gh/stancld/rossum-agents)
|
|
61
|
-
[](#available-tools)
|
|
62
62
|
|
|
63
63
|
[](https://github.com/rossumai/rossum-api)
|
|
64
64
|
[](https://modelcontextprotocol.io/)
|
|
@@ -127,9 +127,29 @@ Configure Claude Desktop (`~/Library/Application Support/Claude/claude_desktop_c
|
|
|
127
127
|
|
|
128
128
|
Set `ROSSUM_MCP_MODE=read-only` to disable all CREATE, UPDATE, and UPLOAD operations. Only GET and LIST operations will be available.
|
|
129
129
|
|
|
130
|
+
### Runtime Mode Switching
|
|
131
|
+
|
|
132
|
+
Two tools allow dynamic mode control:
|
|
133
|
+
|
|
134
|
+
| Tool | Description |
|
|
135
|
+
|------|-------------|
|
|
136
|
+
| `get_mcp_mode` | Returns current operation mode (`read-only` or `read-write`) |
|
|
137
|
+
| `set_mcp_mode` | Switches between modes at runtime |
|
|
138
|
+
|
|
139
|
+
**Use case:** Start in read-only mode for safe exploration, then switch to read-write when ready to make changes.
|
|
140
|
+
|
|
141
|
+
```
|
|
142
|
+
User: What mode are we in?
|
|
143
|
+
Assistant: [calls get_mcp_mode] → "read-only"
|
|
144
|
+
|
|
145
|
+
User: I'm ready to update the schema now.
|
|
146
|
+
Assistant: [calls set_mcp_mode("read-write")] → Mode switched to read-write
|
|
147
|
+
[calls update_schema(...)]
|
|
148
|
+
```
|
|
149
|
+
|
|
130
150
|
## Available Tools
|
|
131
151
|
|
|
132
|
-
The server provides **
|
|
152
|
+
The server provides **59 tools** organized into categories:
|
|
133
153
|
|
|
134
154
|
| Category | Tools | Description |
|
|
135
155
|
|----------|-------|-------------|
|
|
@@ -137,7 +157,7 @@ The server provides **56 tools** organized into categories:
|
|
|
137
157
|
| **Queue Management** | 9 | Create, configure, delete, and list queues |
|
|
138
158
|
| **Schema Management** | 8 | Define, modify, and delete field structures |
|
|
139
159
|
| **Engine Management** | 6 | Configure extraction and splitting engines |
|
|
140
|
-
| **Extensions & Rules** |
|
|
160
|
+
| **Extensions & Rules** | 14 | Webhooks, serverless functions, business rules |
|
|
141
161
|
| **Workspace Management** | 4 | Organize and delete workspaces |
|
|
142
162
|
| **User Management** | 3 | List users and roles |
|
|
143
163
|
| **Relations** | 4 | Annotation and document relations |
|
|
@@ -160,7 +180,7 @@ The server provides **56 tools** organized into categories:
|
|
|
160
180
|
`get_engine`, `list_engines`, `create_engine`, `update_engine`, `create_engine_field`, `get_engine_fields`
|
|
161
181
|
|
|
162
182
|
**Extensions & Rules:**
|
|
163
|
-
`get_hook`, `list_hooks`, `create_hook`, `update_hook`, `list_hook_templates`, `create_hook_from_template`, `list_hook_logs`, `delete_hook`, `get_rule`, `list_rules`, `delete_rule`
|
|
183
|
+
`get_hook`, `list_hooks`, `create_hook`, `update_hook`, `list_hook_templates`, `create_hook_from_template`, `list_hook_logs`, `delete_hook`, `get_rule`, `list_rules`, `create_rule`, `update_rule`, `patch_rule`, `delete_rule`
|
|
164
184
|
|
|
165
185
|
**Workspace Management:**
|
|
166
186
|
`get_workspace`, `list_workspaces`, `create_workspace`, `delete_workspace`
|
|
@@ -69,19 +69,41 @@ class TestToolCatalog:
|
|
|
69
69
|
}
|
|
70
70
|
assert tool_names == expected
|
|
71
71
|
|
|
72
|
-
def
|
|
73
|
-
|
|
74
|
-
(cat_name, t.name) for cat_name, cat in TOOL_CATALOG.items() for t in cat.tools if t.
|
|
72
|
+
def test_write_tools_are_marked(self) -> None:
|
|
73
|
+
write_tools = [
|
|
74
|
+
(cat_name, t.name) for cat_name, cat in TOOL_CATALOG.items() for t in cat.tools if not t.read_only
|
|
75
75
|
]
|
|
76
|
-
|
|
76
|
+
expected_write = {
|
|
77
|
+
("annotations", "upload_document"),
|
|
78
|
+
("annotations", "start_annotation"),
|
|
79
|
+
("annotations", "bulk_update_annotation_fields"),
|
|
80
|
+
("annotations", "confirm_annotation"),
|
|
77
81
|
("annotations", "delete_annotation"),
|
|
82
|
+
("queues", "create_queue"),
|
|
83
|
+
("queues", "update_queue"),
|
|
84
|
+
("queues", "create_queue_from_template"),
|
|
78
85
|
("queues", "delete_queue"),
|
|
86
|
+
("schemas", "update_schema"),
|
|
87
|
+
("schemas", "create_schema"),
|
|
88
|
+
("schemas", "patch_schema"),
|
|
89
|
+
("schemas", "prune_schema_fields"),
|
|
79
90
|
("schemas", "delete_schema"),
|
|
91
|
+
("engines", "update_engine"),
|
|
92
|
+
("engines", "create_engine"),
|
|
93
|
+
("engines", "create_engine_field"),
|
|
94
|
+
("hooks", "create_hook"),
|
|
95
|
+
("hooks", "update_hook"),
|
|
96
|
+
("hooks", "create_hook_from_template"),
|
|
80
97
|
("hooks", "delete_hook"),
|
|
98
|
+
("email_templates", "create_email_template"),
|
|
99
|
+
("rules", "create_rule"),
|
|
100
|
+
("rules", "update_rule"),
|
|
101
|
+
("rules", "patch_rule"),
|
|
81
102
|
("rules", "delete_rule"),
|
|
103
|
+
("workspaces", "create_workspace"),
|
|
82
104
|
("workspaces", "delete_workspace"),
|
|
83
105
|
}
|
|
84
|
-
assert set(
|
|
106
|
+
assert set(write_tools) == expected_write
|
|
85
107
|
|
|
86
108
|
|
|
87
109
|
class TestCatalogSummary:
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
"""Rule tools for Rossum MCP Server."""
|
|
2
|
-
|
|
3
|
-
from __future__ import annotations
|
|
4
|
-
|
|
5
|
-
import logging
|
|
6
|
-
from typing import TYPE_CHECKING
|
|
7
|
-
|
|
8
|
-
from rossum_api.models.rule import Rule
|
|
9
|
-
|
|
10
|
-
from rossum_mcp.tools.base import delete_resource
|
|
11
|
-
|
|
12
|
-
if TYPE_CHECKING:
|
|
13
|
-
from fastmcp import FastMCP
|
|
14
|
-
from rossum_api import AsyncRossumAPIClient
|
|
15
|
-
|
|
16
|
-
logger = logging.getLogger(__name__)
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
async def _get_rule(client: AsyncRossumAPIClient, rule_id: int) -> Rule:
|
|
20
|
-
logger.debug(f"Retrieving rule: rule_id={rule_id}")
|
|
21
|
-
rule: Rule = await client.retrieve_rule(rule_id)
|
|
22
|
-
return rule
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
async def _list_rules(
|
|
26
|
-
client: AsyncRossumAPIClient,
|
|
27
|
-
schema_id: int | None = None,
|
|
28
|
-
organization_id: int | None = None,
|
|
29
|
-
enabled: bool | None = None,
|
|
30
|
-
) -> list[Rule]:
|
|
31
|
-
logger.debug(f"Listing rules: schema_id={schema_id}, organization_id={organization_id}, enabled={enabled}")
|
|
32
|
-
filters: dict = {}
|
|
33
|
-
if schema_id is not None:
|
|
34
|
-
filters["schema"] = schema_id
|
|
35
|
-
if organization_id is not None:
|
|
36
|
-
filters["organization"] = organization_id
|
|
37
|
-
if enabled is not None:
|
|
38
|
-
filters["enabled"] = enabled
|
|
39
|
-
|
|
40
|
-
rules_list: list[Rule] = [rule async for rule in client.list_rules(**filters)]
|
|
41
|
-
return rules_list
|
|
42
|
-
|
|
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
|
-
|
|
48
|
-
def register_rule_tools(mcp: FastMCP, client: AsyncRossumAPIClient) -> None:
|
|
49
|
-
"""Register rule-related tools with the FastMCP server."""
|
|
50
|
-
|
|
51
|
-
@mcp.tool(description="Retrieve rule details.")
|
|
52
|
-
async def get_rule(rule_id: int) -> Rule:
|
|
53
|
-
return await _get_rule(client, rule_id)
|
|
54
|
-
|
|
55
|
-
@mcp.tool(description="List all rules.")
|
|
56
|
-
async def list_rules(
|
|
57
|
-
schema_id: int | None = None, organization_id: int | None = None, enabled: bool | None = None
|
|
58
|
-
) -> list[Rule]:
|
|
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)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|