ims-mcp 1.0.3__py3-none-any.whl → 1.0.5__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.
- ims_mcp/__init__.py +1 -1
- ims_mcp/server.py +38 -3
- {ims_mcp-1.0.3.dist-info → ims_mcp-1.0.5.dist-info}/METADATA +6 -3
- ims_mcp-1.0.5.dist-info/RECORD +9 -0
- ims_mcp-1.0.3.dist-info/RECORD +0 -9
- {ims_mcp-1.0.3.dist-info → ims_mcp-1.0.5.dist-info}/WHEEL +0 -0
- {ims_mcp-1.0.3.dist-info → ims_mcp-1.0.5.dist-info}/entry_points.txt +0 -0
- {ims_mcp-1.0.3.dist-info → ims_mcp-1.0.5.dist-info}/licenses/LICENSE +0 -0
- {ims_mcp-1.0.3.dist-info → ims_mcp-1.0.5.dist-info}/top_level.txt +0 -0
ims_mcp/__init__.py
CHANGED
ims_mcp/server.py
CHANGED
|
@@ -14,10 +14,11 @@ The R2RClient automatically reads these environment variables, so no manual
|
|
|
14
14
|
configuration is needed when running via uvx or other launchers.
|
|
15
15
|
"""
|
|
16
16
|
|
|
17
|
+
import functools
|
|
17
18
|
import os
|
|
18
19
|
import sys
|
|
19
20
|
import uuid
|
|
20
|
-
from r2r import R2RClient
|
|
21
|
+
from r2r import R2RClient, R2RException
|
|
21
22
|
|
|
22
23
|
# Global client instance with authentication
|
|
23
24
|
_authenticated_client = None
|
|
@@ -76,6 +77,34 @@ def get_authenticated_client() -> R2RClient:
|
|
|
76
77
|
return client
|
|
77
78
|
|
|
78
79
|
|
|
80
|
+
def retry_on_auth_error(func):
|
|
81
|
+
"""Decorator to handle token expiry and automatically re-authenticate.
|
|
82
|
+
|
|
83
|
+
When R2R server restarts, all authentication tokens are invalidated.
|
|
84
|
+
This decorator catches 401/403 errors, invalidates the cached client,
|
|
85
|
+
re-authenticates, and retries the request once.
|
|
86
|
+
"""
|
|
87
|
+
def invalidate_client():
|
|
88
|
+
"""Invalidate cached client to force re-authentication."""
|
|
89
|
+
global _authenticated_client
|
|
90
|
+
_authenticated_client = None
|
|
91
|
+
|
|
92
|
+
@functools.wraps(func)
|
|
93
|
+
async def wrapper(*args, **kwargs):
|
|
94
|
+
try:
|
|
95
|
+
return await func(*args, **kwargs)
|
|
96
|
+
except R2RException as e:
|
|
97
|
+
# Check if this is an authentication error (token expired)
|
|
98
|
+
if hasattr(e, 'status_code') and e.status_code in [401, 403]:
|
|
99
|
+
print(f"[ims-mcp] Token expired, re-authenticating...", file=sys.stderr)
|
|
100
|
+
invalidate_client()
|
|
101
|
+
# Retry once with fresh authentication
|
|
102
|
+
return await func(*args, **kwargs)
|
|
103
|
+
# Re-raise non-auth errors
|
|
104
|
+
raise
|
|
105
|
+
return wrapper
|
|
106
|
+
|
|
107
|
+
|
|
79
108
|
def id_to_shorthand(id: str) -> str:
|
|
80
109
|
"""Convert a full ID to shortened version for display."""
|
|
81
110
|
return str(id)[:7]
|
|
@@ -167,6 +196,7 @@ except Exception as e:
|
|
|
167
196
|
|
|
168
197
|
# Search tool with filtering support
|
|
169
198
|
@mcp.tool()
|
|
199
|
+
@retry_on_auth_error
|
|
170
200
|
async def search(
|
|
171
201
|
query: str,
|
|
172
202
|
filters: dict | None = None,
|
|
@@ -216,6 +246,7 @@ async def search(
|
|
|
216
246
|
|
|
217
247
|
# RAG query tool with filtering and generation config
|
|
218
248
|
@mcp.tool()
|
|
249
|
+
@retry_on_auth_error
|
|
219
250
|
async def rag(
|
|
220
251
|
query: str,
|
|
221
252
|
filters: dict | None = None,
|
|
@@ -270,6 +301,7 @@ async def rag(
|
|
|
270
301
|
|
|
271
302
|
# Document upload tool with upsert semantics
|
|
272
303
|
@mcp.tool()
|
|
304
|
+
@retry_on_auth_error
|
|
273
305
|
async def put_document(
|
|
274
306
|
content: str,
|
|
275
307
|
title: str,
|
|
@@ -337,11 +369,12 @@ async def put_document(
|
|
|
337
369
|
|
|
338
370
|
# List documents tool
|
|
339
371
|
@mcp.tool()
|
|
372
|
+
@retry_on_auth_error
|
|
340
373
|
async def list_documents(
|
|
341
374
|
offset: float = 0, # Use float to accept JSON "number" type, convert to int internally
|
|
342
375
|
limit: float = 100, # Use float to accept JSON "number" type, convert to int internally
|
|
343
376
|
document_ids: list[str] | None = None,
|
|
344
|
-
compact_view: bool =
|
|
377
|
+
compact_view: bool = True,
|
|
345
378
|
tags: list[str] | None = None,
|
|
346
379
|
match_all_tags: bool = False,
|
|
347
380
|
) -> str:
|
|
@@ -352,7 +385,7 @@ async def list_documents(
|
|
|
352
385
|
offset: Number of documents to skip (default: 0)
|
|
353
386
|
limit: Maximum number of documents to return (default: 100, max: 100)
|
|
354
387
|
document_ids: Optional list of specific document IDs to retrieve
|
|
355
|
-
compact_view: Show only ID and title (default:
|
|
388
|
+
compact_view: Show only ID and title (default: True - compact view)
|
|
356
389
|
tags: Optional list of tags to filter by (e.g., ["agents", "r1"])
|
|
357
390
|
match_all_tags: If True, document must have ALL tags; if False (default), document must have ANY tag
|
|
358
391
|
|
|
@@ -440,6 +473,7 @@ async def list_documents(
|
|
|
440
473
|
|
|
441
474
|
# Get document tool
|
|
442
475
|
@mcp.tool()
|
|
476
|
+
@retry_on_auth_error
|
|
443
477
|
async def get_document(
|
|
444
478
|
document_id: str | None = None,
|
|
445
479
|
title: str | None = None,
|
|
@@ -530,6 +564,7 @@ async def get_document(
|
|
|
530
564
|
|
|
531
565
|
# Delete document tool
|
|
532
566
|
@mcp.tool()
|
|
567
|
+
@retry_on_auth_error
|
|
533
568
|
async def delete_document(document_id: str) -> str:
|
|
534
569
|
"""
|
|
535
570
|
Delete a document by ID
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ims-mcp
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.5
|
|
4
4
|
Summary: Model Context Protocol server for IMS (Instruction Management Systems)
|
|
5
5
|
Author: Igor Solomatov
|
|
6
6
|
License-Expression: MIT
|
|
@@ -229,13 +229,16 @@ List documents with pagination and optional tag filtering.
|
|
|
229
229
|
- `offset` (int, optional): Documents to skip (default: 0)
|
|
230
230
|
- `limit` (int, optional): Max documents (default: 100)
|
|
231
231
|
- `document_ids` (list[str], optional): Specific IDs to retrieve
|
|
232
|
-
- `compact_view` (bool, optional): Show only ID and title (default:
|
|
232
|
+
- `compact_view` (bool, optional): Show only ID and title (default: True)
|
|
233
233
|
- `tags` (list[str], optional): Filter by tags (e.g., `["agents", "r1"]`)
|
|
234
234
|
- `match_all_tags` (bool, optional): If True, document must have ALL tags; if False (default), document must have ANY tag
|
|
235
235
|
|
|
236
236
|
**Examples:**
|
|
237
237
|
```python
|
|
238
|
-
# List all documents
|
|
238
|
+
# List all documents (compact view - ID and title only)
|
|
239
|
+
list_documents(offset=0, limit=10)
|
|
240
|
+
|
|
241
|
+
# List with full details
|
|
239
242
|
list_documents(offset=0, limit=10, compact_view=False)
|
|
240
243
|
|
|
241
244
|
# Filter by tags (ANY mode - documents with "research" OR "ml")
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
ims_mcp/__init__.py,sha256=jqYWnp0t_xvHX7m0FMHJNOO_3KongXmW-1zwKArilc8,631
|
|
2
|
+
ims_mcp/__main__.py,sha256=z4P1aCVfOgS3cTM2wgJd2pxjMmKCkGkiqYDRGgrspxw,191
|
|
3
|
+
ims_mcp/server.py,sha256=lHdhhVeohXMX9KhqX4mYlHmdOkEH-Ee_k3e7Rg2uNBY,22999
|
|
4
|
+
ims_mcp-1.0.5.dist-info/licenses/LICENSE,sha256=4d1dlH04mbnN3ya4lybcVOUwljRHGy-aSc9MYqGYW44,2534
|
|
5
|
+
ims_mcp-1.0.5.dist-info/METADATA,sha256=GYmWYRXsTNf6ZPq0a6_l7epsERXVLfxuQB3uESR9GL4,9295
|
|
6
|
+
ims_mcp-1.0.5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
7
|
+
ims_mcp-1.0.5.dist-info/entry_points.txt,sha256=xCH9I8g1pTTEqrfjnE-ANHaZo4W6EBJVy0Lg5z8SaIQ,48
|
|
8
|
+
ims_mcp-1.0.5.dist-info/top_level.txt,sha256=wEXA33qFr_eov3S1PY2OF6EQBA2rtAWB_ZNJOzNNQuM,8
|
|
9
|
+
ims_mcp-1.0.5.dist-info/RECORD,,
|
ims_mcp-1.0.3.dist-info/RECORD
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
ims_mcp/__init__.py,sha256=IXSdAG7JlNgU0FZHnI56CEvjhIHzAc3cxuuEINXfbRQ,631
|
|
2
|
-
ims_mcp/__main__.py,sha256=z4P1aCVfOgS3cTM2wgJd2pxjMmKCkGkiqYDRGgrspxw,191
|
|
3
|
-
ims_mcp/server.py,sha256=g_MwgGhVN9jv03qKYTLWNRz_Q-7_cMl9zmbCaVh6LNI,21741
|
|
4
|
-
ims_mcp-1.0.3.dist-info/licenses/LICENSE,sha256=4d1dlH04mbnN3ya4lybcVOUwljRHGy-aSc9MYqGYW44,2534
|
|
5
|
-
ims_mcp-1.0.3.dist-info/METADATA,sha256=TuJNag9JatA25mo5PWAm4hAfsn6FtSJ0MH1UcZyOCv4,9200
|
|
6
|
-
ims_mcp-1.0.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
7
|
-
ims_mcp-1.0.3.dist-info/entry_points.txt,sha256=xCH9I8g1pTTEqrfjnE-ANHaZo4W6EBJVy0Lg5z8SaIQ,48
|
|
8
|
-
ims_mcp-1.0.3.dist-info/top_level.txt,sha256=wEXA33qFr_eov3S1PY2OF6EQBA2rtAWB_ZNJOzNNQuM,8
|
|
9
|
-
ims_mcp-1.0.3.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|