dtlpymcp 0.1.11__py3-none-any.whl → 0.1.13__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.
dtlpymcp/__init__.py CHANGED
@@ -1,3 +1,3 @@
1
1
  from .utils.dtlpy_context import DataloopContext, MCPSource
2
2
 
3
- __version__ = "0.1.11"
3
+ __version__ = "0.1.13"
@@ -20,6 +20,8 @@ logger = logging.getLogger("dtlpymcp")
20
20
  class MCPSource(BaseModel):
21
21
  dpk_name: Optional[str] = None
22
22
  app_url: Optional[str] = None
23
+ dpk_version: Optional[str] = None
24
+ app_trusted: Optional[bool] = None
23
25
  server_url: Optional[str] = None
24
26
  app_jwt: Optional[str] = None
25
27
  tools: Optional[List[Tool]] = []
@@ -60,6 +62,7 @@ class DataloopContext:
60
62
  sources.append(
61
63
  {
62
64
  "dpk_name": app.dpk_name,
65
+ "dpk_version": app.dpk_version,
63
66
  "app_url": next(iter(app.routes.values())),
64
67
  "server_url": None,
65
68
  "app_jwt": None,
@@ -154,6 +157,8 @@ class DataloopContext:
154
157
  app = apps[0]
155
158
  logger.info(f"App: {app.name}")
156
159
  source.app_url = next(iter(app.routes.values()))
160
+ dpk = dl.dpks.get(dpk_name=source.dpk_name, dpk_version=source.dpk_version).to_json()
161
+ source.app_trusted = dpk.get('trusted', False)
157
162
  session = requests.Session()
158
163
  response = session.get(source.app_url, headers=dl.client_api.auth)
159
164
  logger.info(f"App route URL: {response.url}")
@@ -168,14 +173,21 @@ class DataloopContext:
168
173
  def is_expired(app_jwt: str) -> bool:
169
174
  """
170
175
  Check if the APP_JWT is expired.
176
+
177
+ Note: Verification is intentionally skipped - this is only used for
178
+ client-side expiration checking. The server validates the JWT.
171
179
  """
172
180
  try:
173
- decoded = jwt.decode(app_jwt, options={"verify_signature": False})
174
- if decoded.get("exp") < time.time():
175
- return True
176
- return False
177
- except jwt.ExpiredSignatureError:
178
- return True
181
+ decoded = jwt.decode(
182
+ app_jwt,
183
+ options={
184
+ "verify_signature": False,
185
+ "verify_exp": False,
186
+ "verify_aud": False,
187
+ "verify_iss": False,
188
+ },
189
+ )
190
+ return decoded.get("exp", 0) < time.time()
179
191
  except Exception as e:
180
192
  logger.error(f"Error decoding JWT: {e}")
181
193
  return True
@@ -203,9 +215,19 @@ class DataloopContext:
203
215
  def user_info(token: str) -> dict:
204
216
  """
205
217
  Decode a JWT token and return user info.
218
+
219
+ Note: Verification is intentionally skipped - this is only used for
220
+ reading claims client-side. The server validates the JWT.
206
221
  """
207
- decoded = jwt.decode(token, options={"verify_signature": False})
208
- return decoded
222
+ return jwt.decode(
223
+ token,
224
+ options={
225
+ "verify_signature": False,
226
+ "verify_exp": False,
227
+ "verify_aud": False,
228
+ "verify_iss": False,
229
+ },
230
+ )
209
231
 
210
232
  async def list_source_tools(self, source: MCPSource) -> Tuple[str, List[dict], Callable]:
211
233
  """
@@ -214,7 +236,10 @@ class DataloopContext:
214
236
  if source.server_url is None:
215
237
  logger.error("DataloopContext required for DPK servers")
216
238
  raise ValueError("DataloopContext required for DPK servers")
217
- headers = {"Cookie": f"JWT-APP={source.app_jwt}", "x-dl-info": f"{self.token}"}
239
+ if source.app_trusted:
240
+ headers = {"authorization": f"Bearer {self.token}", "x-dl-info": f"{self.token}"}
241
+ else:
242
+ headers = {"Cookie": f"JWT-APP={source.app_jwt}", "x-dl-info": f"{self.token}"}
218
243
  async with streamablehttp_client(source.server_url, headers=headers) as (read, write, _):
219
244
  async with ClientSession(read, write, read_timeout_seconds=timedelta(seconds=60)) as session:
220
245
  await session.initialize()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dtlpymcp
3
- Version: 0.1.11
3
+ Version: 0.1.13
4
4
  Summary: STDIO MCP proxy server for Dataloop platform.
5
5
  Author-email: Your Name <your.email@example.com>
6
6
  Classifier: Programming Language :: Python :: 3.10
@@ -0,0 +1,10 @@
1
+ dtlpymcp/__init__.py,sha256=xwXA73VWK4Kq8rahO55HjkGdKof5CT6kAK4jOWcUqRE,87
2
+ dtlpymcp/__main__.py,sha256=ZsXN8guga8Qo-94bSvgC6u9s5gmmdyppUijb-_bCxCw,1347
3
+ dtlpymcp/min_proxy.py,sha256=QYGoqclGNN7ZMjoLzWBLCxUm4yT2xCoLTbtdFRsqlEk,2572
4
+ dtlpymcp/proxy.py,sha256=IzZrK6s37sXM-AM2L2m_K9AveT7uX_VSxwgrwggJYV4,6213
5
+ dtlpymcp/utils/dtlpy_context.py,sha256=_yA-HiBbq11eZsruiATOo2F2pmAikgohMhEtyc2PZYM,13109
6
+ dtlpymcp-0.1.13.dist-info/METADATA,sha256=s_3QEu8q6HzeEUcbf1_yhrR1BBuwKkeguvpDedZ9Qzc,2190
7
+ dtlpymcp-0.1.13.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
8
+ dtlpymcp-0.1.13.dist-info/entry_points.txt,sha256=6hRVZNTjQevj7erwt9dAOURtPVrSrYu6uHXhAlhTaXQ,52
9
+ dtlpymcp-0.1.13.dist-info/top_level.txt,sha256=z85v20pIEnY3cBaWgwhU3EZS4WAZRywejhIutwd-iHk,9
10
+ dtlpymcp-0.1.13.dist-info/RECORD,,
@@ -1,10 +0,0 @@
1
- dtlpymcp/__init__.py,sha256=-iPfWD7k43HTz0akAm7BHONlJipmtYiMjmF1CCEj0us,87
2
- dtlpymcp/__main__.py,sha256=ZsXN8guga8Qo-94bSvgC6u9s5gmmdyppUijb-_bCxCw,1347
3
- dtlpymcp/min_proxy.py,sha256=QYGoqclGNN7ZMjoLzWBLCxUm4yT2xCoLTbtdFRsqlEk,2572
4
- dtlpymcp/proxy.py,sha256=IzZrK6s37sXM-AM2L2m_K9AveT7uX_VSxwgrwggJYV4,6213
5
- dtlpymcp/utils/dtlpy_context.py,sha256=6ad136vmk0Cstp10cAcY6YaZkUTgFzyvMlocIP6DwiE,12112
6
- dtlpymcp-0.1.11.dist-info/METADATA,sha256=G895DOpzSG2bf9EzmzGIIO2MJgH0RtX6W48Z_eXqnRU,2190
7
- dtlpymcp-0.1.11.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
8
- dtlpymcp-0.1.11.dist-info/entry_points.txt,sha256=6hRVZNTjQevj7erwt9dAOURtPVrSrYu6uHXhAlhTaXQ,52
9
- dtlpymcp-0.1.11.dist-info/top_level.txt,sha256=z85v20pIEnY3cBaWgwhU3EZS4WAZRywejhIutwd-iHk,9
10
- dtlpymcp-0.1.11.dist-info/RECORD,,