ims-mcp 1.0.1__py3-none-any.whl → 1.0.3__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 +66 -6
- {ims_mcp-1.0.1.dist-info → ims_mcp-1.0.3.dist-info}/METADATA +29 -1
- ims_mcp-1.0.3.dist-info/RECORD +9 -0
- ims_mcp-1.0.1.dist-info/RECORD +0 -9
- {ims_mcp-1.0.1.dist-info → ims_mcp-1.0.3.dist-info}/WHEEL +0 -0
- {ims_mcp-1.0.1.dist-info → ims_mcp-1.0.3.dist-info}/entry_points.txt +0 -0
- {ims_mcp-1.0.1.dist-info → ims_mcp-1.0.3.dist-info}/licenses/LICENSE +0 -0
- {ims_mcp-1.0.1.dist-info → ims_mcp-1.0.3.dist-info}/top_level.txt +0 -0
ims_mcp/__init__.py
CHANGED
ims_mcp/server.py
CHANGED
|
@@ -7,14 +7,74 @@ Environment Variables:
|
|
|
7
7
|
R2R_API_BASE or R2R_BASE_URL: R2R server URL (default: http://localhost:7272)
|
|
8
8
|
R2R_COLLECTION: Collection name for queries (optional, uses server default)
|
|
9
9
|
R2R_API_KEY: API key for authentication (optional)
|
|
10
|
+
R2R_EMAIL: Email for authentication (optional, requires R2R_PASSWORD)
|
|
11
|
+
R2R_PASSWORD: Password for authentication (optional, requires R2R_EMAIL)
|
|
10
12
|
|
|
11
13
|
The R2RClient automatically reads these environment variables, so no manual
|
|
12
14
|
configuration is needed when running via uvx or other launchers.
|
|
13
15
|
"""
|
|
14
16
|
|
|
17
|
+
import os
|
|
18
|
+
import sys
|
|
15
19
|
import uuid
|
|
16
20
|
from r2r import R2RClient
|
|
17
21
|
|
|
22
|
+
# Global client instance with authentication
|
|
23
|
+
_authenticated_client = None
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def get_authenticated_client() -> R2RClient:
|
|
27
|
+
"""Get or create an authenticated R2R client.
|
|
28
|
+
|
|
29
|
+
This function handles authentication using either:
|
|
30
|
+
1. API key (R2R_API_KEY) - preferred method
|
|
31
|
+
2. Email/password (R2R_EMAIL + R2R_PASSWORD) - fallback method
|
|
32
|
+
|
|
33
|
+
Returns:
|
|
34
|
+
Authenticated R2RClient instance
|
|
35
|
+
"""
|
|
36
|
+
global _authenticated_client
|
|
37
|
+
|
|
38
|
+
# If client already exists and is authenticated, reuse it
|
|
39
|
+
if _authenticated_client is not None:
|
|
40
|
+
return _authenticated_client
|
|
41
|
+
|
|
42
|
+
# Log startup info (only on first call)
|
|
43
|
+
from ims_mcp import __version__
|
|
44
|
+
base_url = os.getenv('R2R_API_BASE') or os.getenv('R2R_BASE_URL') or 'http://localhost:7272'
|
|
45
|
+
collection = os.getenv('R2R_COLLECTION', 'default')
|
|
46
|
+
api_key = os.getenv('R2R_API_KEY', '')
|
|
47
|
+
email = os.getenv('R2R_EMAIL', '')
|
|
48
|
+
password = os.getenv('R2R_PASSWORD', '')
|
|
49
|
+
|
|
50
|
+
print(f"[ims-mcp v{__version__}]", file=sys.stderr)
|
|
51
|
+
print(f" server={base_url}", file=sys.stderr)
|
|
52
|
+
print(f" collection={collection}", file=sys.stderr)
|
|
53
|
+
print(f" api_key={api_key[:3] + '...' if api_key else 'none'}", file=sys.stderr)
|
|
54
|
+
print(f" email={email if email else 'none'}", file=sys.stderr)
|
|
55
|
+
print(f" password={password[:3] + '...' if password else 'none'}", file=sys.stderr)
|
|
56
|
+
|
|
57
|
+
# Create new client
|
|
58
|
+
client = R2RClient()
|
|
59
|
+
|
|
60
|
+
# Check for email/password authentication
|
|
61
|
+
email = os.getenv("R2R_EMAIL")
|
|
62
|
+
password = os.getenv("R2R_PASSWORD")
|
|
63
|
+
|
|
64
|
+
if email and password:
|
|
65
|
+
try:
|
|
66
|
+
# Login - R2RClient automatically handles token internally
|
|
67
|
+
client.users.login(email=email, password=password)
|
|
68
|
+
print(f"[ims-mcp] Login successful", file=sys.stderr)
|
|
69
|
+
except Exception as e:
|
|
70
|
+
print(f"[ims-mcp] Login failed: {e}", file=sys.stderr)
|
|
71
|
+
# If login fails, continue without authentication (might work for local servers)
|
|
72
|
+
pass
|
|
73
|
+
|
|
74
|
+
# Cache the client for reuse
|
|
75
|
+
_authenticated_client = client
|
|
76
|
+
return client
|
|
77
|
+
|
|
18
78
|
|
|
19
79
|
def id_to_shorthand(id: str) -> str:
|
|
20
80
|
"""Convert a full ID to shortened version for display."""
|
|
@@ -127,7 +187,7 @@ async def search(
|
|
|
127
187
|
Returns:
|
|
128
188
|
Formatted search results from the knowledge base
|
|
129
189
|
"""
|
|
130
|
-
client =
|
|
190
|
+
client = get_authenticated_client()
|
|
131
191
|
|
|
132
192
|
# Only build search_settings if user provided any parameters
|
|
133
193
|
# This preserves original behavior: search("query") → search(query=query) with NO search_settings
|
|
@@ -178,7 +238,7 @@ async def rag(
|
|
|
178
238
|
Returns:
|
|
179
239
|
Generated answer from RAG
|
|
180
240
|
"""
|
|
181
|
-
client =
|
|
241
|
+
client = get_authenticated_client()
|
|
182
242
|
|
|
183
243
|
# Only build configs if user provided parameters
|
|
184
244
|
# This preserves original behavior: rag("query") → rag(query=query) with NO configs
|
|
@@ -228,7 +288,7 @@ async def put_document(
|
|
|
228
288
|
Returns:
|
|
229
289
|
Status message with document_id and operation type
|
|
230
290
|
"""
|
|
231
|
-
client =
|
|
291
|
+
client = get_authenticated_client()
|
|
232
292
|
|
|
233
293
|
# Build metadata with title
|
|
234
294
|
final_metadata = {"title": title}
|
|
@@ -299,7 +359,7 @@ async def list_documents(
|
|
|
299
359
|
Returns:
|
|
300
360
|
Formatted list of documents
|
|
301
361
|
"""
|
|
302
|
-
client =
|
|
362
|
+
client = get_authenticated_client()
|
|
303
363
|
|
|
304
364
|
# Build kwargs for list call
|
|
305
365
|
kwargs = {"offset": int(offset), "limit": min(int(limit), 100)} # Convert to int, cap at 100
|
|
@@ -394,7 +454,7 @@ async def get_document(
|
|
|
394
454
|
Returns:
|
|
395
455
|
Formatted document details
|
|
396
456
|
"""
|
|
397
|
-
client =
|
|
457
|
+
client = get_authenticated_client()
|
|
398
458
|
|
|
399
459
|
# Validate that at least one parameter is provided
|
|
400
460
|
if not document_id and not title:
|
|
@@ -480,7 +540,7 @@ async def delete_document(document_id: str) -> str:
|
|
|
480
540
|
Returns:
|
|
481
541
|
Status message confirming deletion or describing error
|
|
482
542
|
"""
|
|
483
|
-
client =
|
|
543
|
+
client = get_authenticated_client()
|
|
484
544
|
|
|
485
545
|
try:
|
|
486
546
|
# Delete the document
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ims-mcp
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.3
|
|
4
4
|
Summary: Model Context Protocol server for IMS (Instruction Management Systems)
|
|
5
5
|
Author: Igor Solomatov
|
|
6
6
|
License-Expression: MIT
|
|
@@ -82,6 +82,13 @@ The server automatically reads configuration from environment variables:
|
|
|
82
82
|
| `R2R_API_BASE` or `R2R_BASE_URL` | IMS server URL | `http://localhost:7272` |
|
|
83
83
|
| `R2R_COLLECTION` | Collection name for queries | Server default |
|
|
84
84
|
| `R2R_API_KEY` | API key for authentication | None |
|
|
85
|
+
| `R2R_EMAIL` | Email for authentication (requires R2R_PASSWORD) | None |
|
|
86
|
+
| `R2R_PASSWORD` | Password for authentication (requires R2R_EMAIL) | None |
|
|
87
|
+
|
|
88
|
+
**Authentication Priority:**
|
|
89
|
+
1. If `R2R_API_KEY` is set, it will be used
|
|
90
|
+
2. If `R2R_EMAIL` and `R2R_PASSWORD` are set, they will be used to login and obtain an access token
|
|
91
|
+
3. If neither is set, the client will attempt unauthenticated access (works for local servers)
|
|
85
92
|
|
|
86
93
|
**Note:** Environment variables use `R2R_` prefix for compatibility with the underlying R2R SDK.
|
|
87
94
|
|
|
@@ -89,6 +96,8 @@ The server automatically reads configuration from environment variables:
|
|
|
89
96
|
|
|
90
97
|
### Cursor IDE
|
|
91
98
|
|
|
99
|
+
**Local server (no authentication):**
|
|
100
|
+
|
|
92
101
|
Add to `.cursor/mcp.json`:
|
|
93
102
|
|
|
94
103
|
```json
|
|
@@ -106,6 +115,25 @@ Add to `.cursor/mcp.json`:
|
|
|
106
115
|
}
|
|
107
116
|
```
|
|
108
117
|
|
|
118
|
+
**Remote server (with email/password authentication):**
|
|
119
|
+
|
|
120
|
+
```json
|
|
121
|
+
{
|
|
122
|
+
"mcpServers": {
|
|
123
|
+
"KnowledgeBase": {
|
|
124
|
+
"command": "uvx",
|
|
125
|
+
"args": ["ims-mcp"],
|
|
126
|
+
"env": {
|
|
127
|
+
"R2R_API_BASE": "https://your-server.example.com/",
|
|
128
|
+
"R2R_COLLECTION": "your-collection",
|
|
129
|
+
"R2R_EMAIL": "your-email@example.com",
|
|
130
|
+
"R2R_PASSWORD": "your-password"
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
```
|
|
136
|
+
|
|
109
137
|
### Claude Desktop
|
|
110
138
|
|
|
111
139
|
Add to Claude Desktop configuration (`~/Library/Application Support/Claude/claude_desktop_config.json` on macOS):
|
|
@@ -0,0 +1,9 @@
|
|
|
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,,
|
ims_mcp-1.0.1.dist-info/RECORD
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
ims_mcp/__init__.py,sha256=dIRAdqSZq-o4id0nSxuiW276aWMGIaqRgJdXHOuFeZE,631
|
|
2
|
-
ims_mcp/__main__.py,sha256=z4P1aCVfOgS3cTM2wgJd2pxjMmKCkGkiqYDRGgrspxw,191
|
|
3
|
-
ims_mcp/server.py,sha256=Gk3-R8g6E3ULxuMCCfNmqpAa6_cw4boiy5WTWO5smqc,19384
|
|
4
|
-
ims_mcp-1.0.1.dist-info/licenses/LICENSE,sha256=4d1dlH04mbnN3ya4lybcVOUwljRHGy-aSc9MYqGYW44,2534
|
|
5
|
-
ims_mcp-1.0.1.dist-info/METADATA,sha256=UiLxBGHePFVUvQXaVGZ_a08I7ZWIoCcoNBdv2_5M6xU,8350
|
|
6
|
-
ims_mcp-1.0.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
7
|
-
ims_mcp-1.0.1.dist-info/entry_points.txt,sha256=xCH9I8g1pTTEqrfjnE-ANHaZo4W6EBJVy0Lg5z8SaIQ,48
|
|
8
|
-
ims_mcp-1.0.1.dist-info/top_level.txt,sha256=wEXA33qFr_eov3S1PY2OF6EQBA2rtAWB_ZNJOzNNQuM,8
|
|
9
|
-
ims_mcp-1.0.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|