modulector-sdk 2.4.0__tar.gz → 2.6.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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modulector-sdk
3
- Version: 2.4.0
3
+ Version: 2.6.0
4
4
  Summary: Typed Python SDK for the Modulector API.
5
5
  Author: omicsdatascience
6
6
  License-Expression: MIT
@@ -31,10 +31,7 @@ Dynamic: license-file
31
31
 
32
32
  # Modulector SDK
33
33
 
34
- Typed Python SDK for the Modulector API. The package contains client helpers for
35
- querying miRNA target interactions, miRNA aliases, methylation sites, disease
36
- associations, drug associations, and PubMed subscriptions without installing the
37
- Django backend dependencies.
34
+ Typed Python SDK for the Modulector API. The package contains client helpers for querying predicted and experimentally validated miRNA target interactions, miRNA aliases, methylation sites, disease associations, drug associations, and PubMed subscriptions without installing the Django backend dependencies.
38
35
 
39
36
  ## Installation
40
37
 
@@ -45,7 +42,11 @@ pip install modulector-sdk
45
42
  ## Usage
46
43
 
47
44
  ```python
48
- from modulector_sdk import get_mirna_details, get_mirna_target_interactions
45
+ from modulector_sdk import (
46
+ get_mirna_details,
47
+ get_mirna_target_interactions,
48
+ get_mirna_target_validations,
49
+ )
49
50
 
50
51
  details = get_mirna_details("hsa-miR-21-5p")
51
52
  interactions = get_mirna_target_interactions(
@@ -53,6 +54,11 @@ interactions = get_mirna_target_interactions(
53
54
  gene="PTEN",
54
55
  include_pubmeds=True,
55
56
  )
57
+ validations = get_mirna_target_validations(
58
+ mirna="hsa-miR-122-5p",
59
+ target="SLC7A1",
60
+ experiment="Western blot",
61
+ )
56
62
  ```
57
63
 
58
64
  Set `MODULECTOR_API_BASE_URL` to target a different Modulector deployment:
@@ -95,11 +101,10 @@ modulector-mcp --transport streamable-http --host 127.0.0.1 --port 8000
95
101
 
96
102
  Then connect the client to `http://127.0.0.1:8000/mcp`.
97
103
 
98
- The server includes tools for miRNA target interactions, miRNA details and
99
- aliases, miRNA identifier resolution, methylation site lookup and annotation,
100
- disease associations, drug associations, and PubMed news subscriptions. Use
101
- `MODULECTOR_API_BASE_URL` or each tool's `base_url` argument to target a custom
102
- Modulector deployment.
104
+ The server includes tools for predicted and experimentally validated miRNA target interactions, miRNA details and aliases, miRNA identifier resolution, methylation site lookup and annotation, disease associations, drug associations, and PubMed news subscriptions. Use `MODULECTOR_API_BASE_URL` or each tool's `base_url` argument to target a custom Modulector deployment.
105
+
106
+ When deployed with the root Docker Compose stack, nginx proxies the MCP
107
+ Streamable HTTP endpoint at `https://<mydomain.com>/mcp`.
103
108
 
104
109
  ## Development
105
110
 
@@ -1,9 +1,6 @@
1
1
  # Modulector SDK
2
2
 
3
- Typed Python SDK for the Modulector API. The package contains client helpers for
4
- querying miRNA target interactions, miRNA aliases, methylation sites, disease
5
- associations, drug associations, and PubMed subscriptions without installing the
6
- Django backend dependencies.
3
+ Typed Python SDK for the Modulector API. The package contains client helpers for querying predicted and experimentally validated miRNA target interactions, miRNA aliases, methylation sites, disease associations, drug associations, and PubMed subscriptions without installing the Django backend dependencies.
7
4
 
8
5
  ## Installation
9
6
 
@@ -14,7 +11,11 @@ pip install modulector-sdk
14
11
  ## Usage
15
12
 
16
13
  ```python
17
- from modulector_sdk import get_mirna_details, get_mirna_target_interactions
14
+ from modulector_sdk import (
15
+ get_mirna_details,
16
+ get_mirna_target_interactions,
17
+ get_mirna_target_validations,
18
+ )
18
19
 
19
20
  details = get_mirna_details("hsa-miR-21-5p")
20
21
  interactions = get_mirna_target_interactions(
@@ -22,6 +23,11 @@ interactions = get_mirna_target_interactions(
22
23
  gene="PTEN",
23
24
  include_pubmeds=True,
24
25
  )
26
+ validations = get_mirna_target_validations(
27
+ mirna="hsa-miR-122-5p",
28
+ target="SLC7A1",
29
+ experiment="Western blot",
30
+ )
25
31
  ```
26
32
 
27
33
  Set `MODULECTOR_API_BASE_URL` to target a different Modulector deployment:
@@ -64,11 +70,10 @@ modulector-mcp --transport streamable-http --host 127.0.0.1 --port 8000
64
70
 
65
71
  Then connect the client to `http://127.0.0.1:8000/mcp`.
66
72
 
67
- The server includes tools for miRNA target interactions, miRNA details and
68
- aliases, miRNA identifier resolution, methylation site lookup and annotation,
69
- disease associations, drug associations, and PubMed news subscriptions. Use
70
- `MODULECTOR_API_BASE_URL` or each tool's `base_url` argument to target a custom
71
- Modulector deployment.
73
+ The server includes tools for predicted and experimentally validated miRNA target interactions, miRNA details and aliases, miRNA identifier resolution, methylation site lookup and annotation, disease associations, drug associations, and PubMed news subscriptions. Use `MODULECTOR_API_BASE_URL` or each tool's `base_url` argument to target a custom Modulector deployment.
74
+
75
+ When deployed with the root Docker Compose stack, nginx proxies the MCP
76
+ Streamable HTTP endpoint at `https://<mydomain.com>/mcp`.
72
77
 
73
78
  ## Development
74
79
 
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "modulector-sdk"
7
- version = "2.4.0"
7
+ version = "2.6.0"
8
8
  description = "Typed Python SDK for the Modulector API."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -9,8 +9,10 @@ from .services import (
9
9
  MirnaDisease,
10
10
  MirnaDrug,
11
11
  MirnaTargetInteraction,
12
+ MirnaTargetValidation,
12
13
  SourceLink,
13
14
  SubscribePubmedsResponse,
15
+ SupportType,
14
16
  UcscCpgIsland,
15
17
  find_methylation_sites,
16
18
  find_mirna_codes,
@@ -23,6 +25,7 @@ from .services import (
23
25
  get_mirna_codes,
24
26
  get_mirna_details,
25
27
  get_mirna_target_interactions,
28
+ get_mirna_target_validations,
26
29
  subscribe_pubmeds,
27
30
  unsubscribe_pubmeds,
28
31
  )
@@ -44,9 +47,11 @@ __all__ = [
44
47
  "MirnaDisease",
45
48
  "MirnaDrug",
46
49
  "MirnaTargetInteraction",
50
+ "MirnaTargetValidation",
47
51
  "PaginatedResponse",
48
52
  "SourceLink",
49
53
  "SubscribePubmedsResponse",
54
+ "SupportType",
50
55
  "UcscCpgIsland",
51
56
  "find_methylation_sites",
52
57
  "find_mirna_codes",
@@ -60,6 +65,7 @@ __all__ = [
60
65
  "get_mirna_codes",
61
66
  "get_mirna_details",
62
67
  "get_mirna_target_interactions",
68
+ "get_mirna_target_validations",
63
69
  "get_paginated_response",
64
70
  "get_simple_response",
65
71
  "iter_paginated_results",
@@ -3,29 +3,38 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  import argparse
6
+ import os
6
7
  from typing import Any, Final, Literal, TypeVar, cast
8
+ from urllib.parse import urlparse
7
9
 
8
10
  from mcp.server.fastmcp import FastMCP
11
+ from mcp.server.transport_security import TransportSecuritySettings
9
12
 
10
13
  from . import services
14
+ from .services import SupportType
11
15
  from .utils import PaginatedResponse
12
16
 
13
17
  T = TypeVar("T")
14
18
  Transport = Literal["stdio", "sse", "streamable-http"]
15
19
 
16
20
  SERVER_INSTRUCTIONS: Final[str] = (
17
- "Use Modulector to help researchers inspect human miRNA target "
18
- "interactions, miRNA aliases, disease and drug associations, and "
21
+ "Use Modulector to help researchers inspect predicted and experimentally "
22
+ "validated human miRNA target interactions, miRNA aliases, disease and "
23
+ "drug associations, and "
19
24
  "Illumina methylation site annotations. Prefer finder tools when the "
20
25
  "user gives partial or uncertain identifiers, then use the detail or "
21
26
  "paginated tools with explicit identifiers. The returned data comes from "
22
27
  "the configured Modulector API deployment."
23
28
  )
29
+ PUBLIC_BASE_URL: Final[str] = os.getenv(
30
+ "MODULECTOR_PUBLIC_BASE_URL",
31
+ services.MODULECTOR_API_BASE_URL,
32
+ )
24
33
 
25
34
  mcp = FastMCP(
26
35
  name="modulector",
27
36
  instructions=SERVER_INSTRUCTIONS,
28
- website_url=services.MODULECTOR_API_BASE_URL,
37
+ website_url=PUBLIC_BASE_URL,
29
38
  )
30
39
 
31
40
 
@@ -43,11 +52,13 @@ def about_modulector() -> str:
43
52
 
44
53
  return (
45
54
  "# Modulector\n\n"
46
- "Modulector provides programmatic access to curated human miRNA target "
47
- "interactions, miRNA aliases, miRNA-disease associations, "
55
+ "Modulector provides programmatic access to predicted and "
56
+ "experimentally validated human miRNA target interactions, miRNA "
57
+ "aliases, miRNA-disease associations, "
48
58
  "miRNA-drug associations, and Illumina Infinium MethylationEPIC 2.0 "
49
59
  "site annotations.\n\n"
50
60
  f"Default API base URL: `{services.MODULECTOR_API_BASE_URL}`\n\n"
61
+ f"Public website URL: `{PUBLIC_BASE_URL}`\n\n"
51
62
  "Use the finder tools for partial identifiers, then query detail or "
52
63
  "paginated tools with exact miRNA, gene, disease, drug, or methylation "
53
64
  "site filters."
@@ -96,7 +107,7 @@ def get_mirna_target_interactions(
96
107
  :param gene: Gene symbol.
97
108
  :param score: Minimum MirDIP score between 0 and 1.
98
109
  :param include_pubmeds: Whether to include PubMed URLs for interactions.
99
- :param ordering: Comma-separated ordering fields, such as ``-score,gene``.
110
+ :param ordering: Comma-separated ordering fields, such as `-score,gene`.
100
111
  :param search: Search term for supported server-side fields.
101
112
  :param page: Page number to request.
102
113
  :param page_size: Number of records to request.
@@ -121,6 +132,48 @@ def get_mirna_target_interactions(
121
132
  )
122
133
 
123
134
 
135
+ @mcp.tool()
136
+ def get_mirna_target_validations(
137
+ mirna: str | None = None,
138
+ target: str | None = None,
139
+ support_type: SupportType | None = None,
140
+ experiment: str | None = None,
141
+ ordering: str | None = None,
142
+ page: int | None = None,
143
+ page_size: int | None = None,
144
+ base_url: str | None = None,
145
+ timeout: float = 30.0,
146
+ ) -> dict[str, Any]:
147
+ """Return experimentally validated miRNA-target interactions.
148
+
149
+ :param mirna: Exact standardized miRNA identifier.
150
+ :param target: Exact target gene symbol.
151
+ :param support_type: Exact miRTarBase support classification.
152
+ :param experiment: Case-insensitive partial experiment name, such as
153
+ `Western blot`.
154
+ :param ordering: Comma-separated `mirna` or `gene` ordering fields.
155
+ :param page: Page number to request.
156
+ :param page_size: Number of records to request.
157
+ :param base_url: Optional Modulector API deployment URL.
158
+ :param timeout: Request timeout in seconds.
159
+ :return: Paginated miRTarBase validation records.
160
+ """
161
+
162
+ return _page_to_dict(
163
+ services.get_mirna_target_validations(
164
+ base_url=_base_url(base_url),
165
+ mirna=mirna,
166
+ target=target,
167
+ support_type=support_type,
168
+ experiment=experiment,
169
+ ordering=ordering,
170
+ page=page,
171
+ page_size=page_size,
172
+ timeout=timeout,
173
+ )
174
+ )
175
+
176
+
124
177
  @mcp.tool()
125
178
  def get_mirna_details(
126
179
  mirna: str,
@@ -135,10 +188,13 @@ def get_mirna_details(
135
188
  :return: miRNA detail record.
136
189
  """
137
190
 
138
- return services.get_mirna_details(
139
- mirna,
140
- base_url=_base_url(base_url),
141
- timeout=timeout,
191
+ return cast(
192
+ dict[str, Any],
193
+ services.get_mirna_details(
194
+ mirna,
195
+ base_url=_base_url(base_url),
196
+ timeout=timeout,
197
+ ),
142
198
  )
143
199
 
144
200
 
@@ -308,10 +364,13 @@ def get_methylation_details(
308
364
  :return: Methylation site detail record.
309
365
  """
310
366
 
311
- return services.get_methylation_details(
312
- methylation_site,
313
- base_url=_base_url(base_url),
314
- timeout=timeout,
367
+ return cast(
368
+ dict[str, Any],
369
+ services.get_methylation_details(
370
+ methylation_site,
371
+ base_url=_base_url(base_url),
372
+ timeout=timeout,
373
+ ),
315
374
  )
316
375
 
317
376
 
@@ -400,6 +459,7 @@ def main() -> None:
400
459
  mcp.settings.host = args.host
401
460
  mcp.settings.port = args.port
402
461
  mcp.settings.json_response = args.json_response
462
+ _configure_http_transport_security()
403
463
  mcp.run(transport=transport)
404
464
 
405
465
 
@@ -447,6 +507,63 @@ def _base_url(base_url: str | None) -> str:
447
507
  return base_url or services.MODULECTOR_API_BASE_URL
448
508
 
449
509
 
510
+ def _configure_http_transport_security() -> None:
511
+ """Configure DNS rebinding protection for HTTP MCP transports.
512
+
513
+ :return: None.
514
+ """
515
+
516
+ mcp.settings.transport_security = TransportSecuritySettings(
517
+ allowed_hosts=_allowed_hosts(),
518
+ allowed_origins=_allowed_origins(),
519
+ )
520
+
521
+
522
+ def _allowed_hosts() -> list[str]:
523
+ """Return allowed Host headers for the MCP HTTP transport.
524
+
525
+ :return: Host header allow-list.
526
+ """
527
+
528
+ configured_hosts = _csv_env("MODULECTOR_MCP_ALLOWED_HOSTS")
529
+ if configured_hosts:
530
+ return configured_hosts
531
+
532
+ parsed_public_url = urlparse(PUBLIC_BASE_URL)
533
+ public_host = parsed_public_url.netloc
534
+ hosts = ["127.0.0.1:*", "localhost:*", "[::1]:*"]
535
+ if public_host:
536
+ hosts.append(public_host)
537
+ return hosts
538
+
539
+
540
+ def _allowed_origins() -> list[str]:
541
+ """Return allowed Origin headers for the MCP HTTP transport.
542
+
543
+ :return: Origin header allow-list.
544
+ """
545
+
546
+ configured_origins = _csv_env("MODULECTOR_MCP_ALLOWED_ORIGINS")
547
+ if configured_origins:
548
+ return configured_origins
549
+
550
+ parsed_public_url = urlparse(PUBLIC_BASE_URL)
551
+ origins = ["http://127.0.0.1:*", "http://localhost:*", "http://[::1]:*"]
552
+ if parsed_public_url.scheme and parsed_public_url.netloc:
553
+ origins.append(f"{parsed_public_url.scheme}://{parsed_public_url.netloc}")
554
+ return origins
555
+
556
+
557
+ def _csv_env(name: str) -> list[str]:
558
+ """Return comma-separated environment variable values.
559
+
560
+ :param name: Environment variable name.
561
+ :return: Non-empty stripped values.
562
+ """
563
+
564
+ return [value.strip() for value in os.getenv(name, "").split(",") if value.strip()]
565
+
566
+
450
567
  def _page_to_dict(page: PaginatedResponse[T]) -> dict[str, Any]:
451
568
  """Convert a paginated SDK response into a JSON-serializable mapping.
452
569
 
@@ -24,6 +24,12 @@ FINDER_LIMIT_MAX: Final[int] = 3000
24
24
 
25
25
  Ordering = str | Sequence[str]
26
26
  ScoreClass = Literal["V", "H", "M", "L"]
27
+ SupportType = Literal[
28
+ "Functional MTI",
29
+ "Functional MTI (Weak)",
30
+ "Non-Functional MTI",
31
+ "Non-Functional MTI (Weak)",
32
+ ]
27
33
 
28
34
 
29
35
  class SourceLink(TypedDict):
@@ -99,6 +105,34 @@ class MirnaTargetInteraction(TypedDict):
99
105
  """MirDIP score class for the interaction."""
100
106
 
101
107
 
108
+ class MirnaTargetValidation(TypedDict):
109
+ """One experimentally validated miRNA-target interaction record."""
110
+
111
+ id: int
112
+ """Internal record identifier."""
113
+
114
+ mirtarbase_id: str
115
+ """Interaction identifier assigned by miRTarBase."""
116
+
117
+ mirna: str
118
+ """Standardized miRNA identifier."""
119
+
120
+ gene: str
121
+ """Target gene symbol."""
122
+
123
+ target_gene_entrez_id: str | None
124
+ """Entrez identifier for the target gene, when available."""
125
+
126
+ experiments: list[str]
127
+ """Techniques used to validate the miRNA-target interaction."""
128
+
129
+ support_type: SupportType
130
+ """Classification of the experimental support."""
131
+
132
+ pmid: str
133
+ """PubMed identifier for the supporting publication."""
134
+
135
+
102
136
  class MirnaDisease(TypedDict):
103
137
  """One miRNA disease association record."""
104
138
 
@@ -208,18 +242,18 @@ def get_mirna_target_interactions(
208
242
  :param mirna: miRNA accession ID or miRBase name.
209
243
  :param gene: Gene symbol.
210
244
  :param score: Minimum mirDIP interaction score. Valid values are between
211
- ``0`` and ``1``.
245
+ `0` and `1`.
212
246
  :param include_pubmeds: Whether PubMed links should be included.
213
247
  :param ordering: Ordering field or comma-separated fields. Prefix a field
214
- with ``-`` for descending order.
248
+ with `-` for descending order.
215
249
  :param search: Search term for supported server-side search fields.
216
250
  :param page: Page number to request.
217
251
  :param page_size: Number of records per page.
218
252
  :param headers: Optional HTTP headers.
219
253
  :param timeout: Request timeout in seconds.
220
- :param session: Optional ``requests.Session`` to use for the request.
221
- :raises ValueError: If neither ``mirna`` nor ``gene`` is provided, or if
222
- ``score`` is outside the accepted range.
254
+ :param session: Optional `requests.Session` to use for the request.
255
+ :raises ValueError: If neither `mirna` nor `gene` is provided, or if
256
+ `score` is outside the accepted range.
223
257
  :return: Paginated miRNA target interaction records.
224
258
  """
225
259
 
@@ -248,6 +282,60 @@ def get_mirna_target_interactions(
248
282
  return cast(PaginatedResponse[MirnaTargetInteraction], response)
249
283
 
250
284
 
285
+ def get_mirna_target_validations(
286
+ base_url: str = MODULECTOR_API_BASE_URL,
287
+ mirna: str | None = None,
288
+ target: str | None = None,
289
+ support_type: SupportType | None = None,
290
+ experiment: str | None = None,
291
+ ordering: Ordering | None = None,
292
+ page: int | None = None,
293
+ page_size: int | None = None,
294
+ headers: Headers = None,
295
+ timeout: float = 30.0,
296
+ session: requests.Session | None = None,
297
+ ) -> PaginatedResponse[MirnaTargetValidation]:
298
+ """Return experimentally validated miRNA-target interactions.
299
+
300
+ :param base_url: Base URL of the Modulector API.
301
+ :param mirna: Exact standardized miRNA identifier.
302
+ :param target: Exact target gene symbol.
303
+ :param support_type: Exact miRTarBase support classification.
304
+ :param experiment: Case-insensitive partial experiment name.
305
+ :param ordering: Ordering field or comma-separated fields. Supported fields
306
+ are `mirna` and `gene`; prefix a field with `-` for descending
307
+ order.
308
+ :param page: Page number to request.
309
+ :param page_size: Number of records per page.
310
+ :param headers: Optional HTTP headers.
311
+ :param timeout: Request timeout in seconds.
312
+ :param session: Optional `requests.Session` to use for the request.
313
+ :raises ValueError: If neither `mirna` nor `target` is provided.
314
+ :return: Paginated experimentally validated interaction records.
315
+ """
316
+
317
+ if mirna is None and target is None:
318
+ raise ValueError("mirna or target is required")
319
+
320
+ params = _request_params(
321
+ mirna=mirna,
322
+ target=target,
323
+ support_type=support_type,
324
+ experiment=experiment,
325
+ ordering=_format_ordering(ordering),
326
+ )
327
+ response = get_paginated_response(
328
+ _build_url(base_url, "mirna-target-validation"),
329
+ params=params,
330
+ page=page,
331
+ page_size=page_size,
332
+ headers=headers,
333
+ timeout=timeout,
334
+ session=session,
335
+ )
336
+ return cast(PaginatedResponse[MirnaTargetValidation], response)
337
+
338
+
251
339
  def get_mirna_details(
252
340
  mirna: str,
253
341
  *,
@@ -262,7 +350,7 @@ def get_mirna_details(
262
350
  :param base_url: Base URL of the Modulector API.
263
351
  :param headers: Optional HTTP headers.
264
352
  :param timeout: Request timeout in seconds.
265
- :param session: Optional ``requests.Session`` to use for the request.
353
+ :param session: Optional `requests.Session` to use for the request.
266
354
  :return: miRNA aliases, sequence, accession ID, and source links.
267
355
  """
268
356
 
@@ -298,12 +386,12 @@ def get_mirna_aliases(
298
386
  :param previous_mature_mirna: Exact previous mature miRNA filter.
299
387
  :param search: Case-insensitive search across identifier fields.
300
388
  :param ordering: Ordering field or comma-separated fields. Prefix a field
301
- with ``-`` for descending order.
389
+ with `-` for descending order.
302
390
  :param page: Page number to request.
303
391
  :param page_size: Number of records per page.
304
392
  :param headers: Optional HTTP headers.
305
393
  :param timeout: Request timeout in seconds.
306
- :param session: Optional ``requests.Session`` to use for the request.
394
+ :param session: Optional `requests.Session` to use for the request.
307
395
  :return: Paginated miRNA alias records.
308
396
  """
309
397
 
@@ -340,12 +428,12 @@ def find_mirna_codes(
340
428
  :param query: miRNA search string.
341
429
  :param base_url: Base URL of the Modulector API.
342
430
  :param limit: Maximum number of returned values. The API accepts values up
343
- to ``3000``.
431
+ to `3000`.
344
432
  :param headers: Optional HTTP headers.
345
433
  :param timeout: Request timeout in seconds.
346
- :param session: Optional ``requests.Session`` to use for the request.
347
- :raises ValueError: If ``limit`` is less than ``1`` or greater than
348
- ``3000``.
434
+ :param session: Optional `requests.Session` to use for the request.
435
+ :raises ValueError: If `limit` is less than `1` or greater than
436
+ `3000`.
349
437
  :return: Matching miRNA IDs or accession IDs.
350
438
  """
351
439
 
@@ -374,9 +462,9 @@ def get_mirna_codes(
374
462
  :param base_url: Base URL of the Modulector API.
375
463
  :param headers: Optional HTTP headers.
376
464
  :param timeout: Request timeout in seconds.
377
- :param session: Optional ``requests.Session`` to use for the request.
465
+ :param session: Optional `requests.Session` to use for the request.
378
466
  :return: Mapping from each requested identifier to its accession ID, or
379
- ``None`` when no accession ID is found.
467
+ `None` when no accession ID is found.
380
468
  """
381
469
 
382
470
  payload = get_simple_response(
@@ -404,12 +492,12 @@ def find_methylation_sites(
404
492
  :param query: Methylation site search string.
405
493
  :param base_url: Base URL of the Modulector API.
406
494
  :param limit: Maximum number of returned values. The API accepts values up
407
- to ``3000``.
495
+ to `3000`.
408
496
  :param headers: Optional HTTP headers.
409
497
  :param timeout: Request timeout in seconds.
410
- :param session: Optional ``requests.Session`` to use for the request.
411
- :raises ValueError: If ``limit`` is less than ``1`` or greater than
412
- ``3000``.
498
+ :param session: Optional `requests.Session` to use for the request.
499
+ :raises ValueError: If `limit` is less than `1` or greater than
500
+ `3000`.
413
501
  :return: Matching methylation site names.
414
502
  """
415
503
 
@@ -438,7 +526,7 @@ def get_methylation_sites(
438
526
  :param base_url: Base URL of the Modulector API.
439
527
  :param headers: Optional HTTP headers.
440
528
  :param timeout: Request timeout in seconds.
441
- :param session: Optional ``requests.Session`` to use for the request.
529
+ :param session: Optional `requests.Session` to use for the request.
442
530
  :return: Mapping from each requested identifier to matching EPIC 2.0 site
443
531
  names.
444
532
  """
@@ -468,7 +556,7 @@ def get_methylation_site_genes(
468
556
  :param base_url: Base URL of the Modulector API.
469
557
  :param headers: Optional HTTP headers.
470
558
  :param timeout: Request timeout in seconds.
471
- :param session: Optional ``requests.Session`` to use for the request.
559
+ :param session: Optional `requests.Session` to use for the request.
472
560
  :return: Mapping from each requested identifier to associated genes.
473
561
  """
474
562
 
@@ -498,7 +586,7 @@ def get_methylation_details(
498
586
  :param base_url: Base URL of the Modulector API.
499
587
  :param headers: Optional HTTP headers.
500
588
  :param timeout: Request timeout in seconds.
501
- :param session: Optional ``requests.Session`` to use for the request.
589
+ :param session: Optional `requests.Session` to use for the request.
502
590
  :return: Methylation site details, aliases, CpG island relations, and genes.
503
591
  """
504
592
 
@@ -531,12 +619,12 @@ def get_diseases(
531
619
  returned page by page.
532
620
  :param search: Case-insensitive search term for disease names.
533
621
  :param ordering: Ordering field or comma-separated fields. Prefix a field
534
- with ``-`` for descending order.
622
+ with `-` for descending order.
535
623
  :param page: Page number to request.
536
624
  :param page_size: Number of records per page.
537
625
  :param headers: Optional HTTP headers.
538
626
  :param timeout: Request timeout in seconds.
539
- :param session: Optional ``requests.Session`` to use for the request.
627
+ :param session: Optional `requests.Session` to use for the request.
540
628
  :return: Paginated miRNA disease association records.
541
629
  """
542
630
 
@@ -579,12 +667,12 @@ def get_drugs(
579
667
  :param search: Case-insensitive search term for condition, small molecule,
580
668
  and expression pattern fields.
581
669
  :param ordering: Ordering field or comma-separated fields. Prefix a field
582
- with ``-`` for descending order.
670
+ with `-` for descending order.
583
671
  :param page: Page number to request.
584
672
  :param page_size: Number of records per page.
585
673
  :param headers: Optional HTTP headers.
586
674
  :param timeout: Request timeout in seconds.
587
- :param session: Optional ``requests.Session`` to use for the request.
675
+ :param session: Optional `requests.Session` to use for the request.
588
676
  :return: Paginated miRNA drug association records.
589
677
  """
590
678
 
@@ -624,7 +712,7 @@ def subscribe_pubmeds(
624
712
  :param gene: Optional gene symbol filter for the subscription.
625
713
  :param headers: Optional HTTP headers.
626
714
  :param timeout: Request timeout in seconds.
627
- :param session: Optional ``requests.Session`` to use for the request.
715
+ :param session: Optional `requests.Session` to use for the request.
628
716
  :return: Subscription token response.
629
717
  """
630
718
 
@@ -648,11 +736,11 @@ def unsubscribe_pubmeds(
648
736
  ) -> str:
649
737
  """Unsubscribe from PubMed news.
650
738
 
651
- :param token: Subscription token returned by ``subscribe_pubmeds``.
739
+ :param token: Subscription token returned by `subscribe_pubmeds`.
652
740
  :param base_url: Base URL of the Modulector API.
653
741
  :param headers: Optional HTTP headers.
654
742
  :param timeout: Request timeout in seconds.
655
- :param session: Optional ``requests.Session`` to use for the request.
743
+ :param session: Optional `requests.Session` to use for the request.
656
744
  :return: API confirmation message.
657
745
  """
658
746
 
@@ -678,10 +766,10 @@ def _build_url(base_url: str, endpoint: str) -> str:
678
766
 
679
767
 
680
768
  def _request_params(**params: Any) -> dict[str, Any]:
681
- """Return request parameters without ``None`` values.
769
+ """Return request parameters without `None` values.
682
770
 
683
771
  :param params: Query parameters keyed by API parameter name.
684
- :return: A dictionary containing only parameters with non-``None`` values.
772
+ :return: A dictionary containing only parameters with non-`None` values.
685
773
  """
686
774
 
687
775
  return {key: value for key, value in params.items() if value is not None}
@@ -691,7 +779,7 @@ def _bool_param(value: bool | None) -> str | None:
691
779
  """Convert an optional boolean to the API's lowercase string form.
692
780
 
693
781
  :param value: Boolean value to convert.
694
- :return: ``"true"``, ``"false"``, or ``None``.
782
+ :return: `"true"`, `"false"`, or `None`.
695
783
  """
696
784
 
697
785
  if value is None:
@@ -704,7 +792,7 @@ def _format_ordering(ordering: Ordering | None) -> str | None:
704
792
 
705
793
  :param ordering: A comma-separated ordering string or a sequence of ordering
706
794
  fields.
707
- :return: A comma-separated ordering string, or ``None``.
795
+ :return: A comma-separated ordering string, or `None`.
708
796
  """
709
797
 
710
798
  if ordering is None:
@@ -722,8 +810,8 @@ def _validate_limit(limit: int | None) -> None:
722
810
  """Validate finder service limit parameters.
723
811
 
724
812
  :param limit: Limit value to validate.
725
- :raises ValueError: If ``limit`` is outside the API's accepted range.
726
- :return: ``None``.
813
+ :raises ValueError: If `limit` is outside the API's accepted range.
814
+ :return: `None`.
727
815
  """
728
816
 
729
817
  if limit is not None and not 1 <= limit <= FINDER_LIMIT_MAX:
@@ -739,8 +827,10 @@ __all__ = [
739
827
  "MirnaDisease",
740
828
  "MirnaDrug",
741
829
  "MirnaTargetInteraction",
830
+ "MirnaTargetValidation",
742
831
  "SourceLink",
743
832
  "SubscribePubmedsResponse",
833
+ "SupportType",
744
834
  "UcscCpgIsland",
745
835
  "find_methylation_sites",
746
836
  "find_mirna_codes",
@@ -753,6 +843,7 @@ __all__ = [
753
843
  "get_mirna_codes",
754
844
  "get_mirna_details",
755
845
  "get_mirna_target_interactions",
846
+ "get_mirna_target_validations",
756
847
  "subscribe_pubmeds",
757
848
  "unsubscribe_pubmeds",
758
849
  ]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modulector-sdk
3
- Version: 2.4.0
3
+ Version: 2.6.0
4
4
  Summary: Typed Python SDK for the Modulector API.
5
5
  Author: omicsdatascience
6
6
  License-Expression: MIT
@@ -31,10 +31,7 @@ Dynamic: license-file
31
31
 
32
32
  # Modulector SDK
33
33
 
34
- Typed Python SDK for the Modulector API. The package contains client helpers for
35
- querying miRNA target interactions, miRNA aliases, methylation sites, disease
36
- associations, drug associations, and PubMed subscriptions without installing the
37
- Django backend dependencies.
34
+ Typed Python SDK for the Modulector API. The package contains client helpers for querying predicted and experimentally validated miRNA target interactions, miRNA aliases, methylation sites, disease associations, drug associations, and PubMed subscriptions without installing the Django backend dependencies.
38
35
 
39
36
  ## Installation
40
37
 
@@ -45,7 +42,11 @@ pip install modulector-sdk
45
42
  ## Usage
46
43
 
47
44
  ```python
48
- from modulector_sdk import get_mirna_details, get_mirna_target_interactions
45
+ from modulector_sdk import (
46
+ get_mirna_details,
47
+ get_mirna_target_interactions,
48
+ get_mirna_target_validations,
49
+ )
49
50
 
50
51
  details = get_mirna_details("hsa-miR-21-5p")
51
52
  interactions = get_mirna_target_interactions(
@@ -53,6 +54,11 @@ interactions = get_mirna_target_interactions(
53
54
  gene="PTEN",
54
55
  include_pubmeds=True,
55
56
  )
57
+ validations = get_mirna_target_validations(
58
+ mirna="hsa-miR-122-5p",
59
+ target="SLC7A1",
60
+ experiment="Western blot",
61
+ )
56
62
  ```
57
63
 
58
64
  Set `MODULECTOR_API_BASE_URL` to target a different Modulector deployment:
@@ -95,11 +101,10 @@ modulector-mcp --transport streamable-http --host 127.0.0.1 --port 8000
95
101
 
96
102
  Then connect the client to `http://127.0.0.1:8000/mcp`.
97
103
 
98
- The server includes tools for miRNA target interactions, miRNA details and
99
- aliases, miRNA identifier resolution, methylation site lookup and annotation,
100
- disease associations, drug associations, and PubMed news subscriptions. Use
101
- `MODULECTOR_API_BASE_URL` or each tool's `base_url` argument to target a custom
102
- Modulector deployment.
104
+ The server includes tools for predicted and experimentally validated miRNA target interactions, miRNA details and aliases, miRNA identifier resolution, methylation site lookup and annotation, disease associations, drug associations, and PubMed news subscriptions. Use `MODULECTOR_API_BASE_URL` or each tool's `base_url` argument to target a custom Modulector deployment.
105
+
106
+ When deployed with the root Docker Compose stack, nginx proxies the MCP
107
+ Streamable HTTP endpoint at `https://<mydomain.com>/mcp`.
103
108
 
104
109
  ## Development
105
110
 
File without changes
File without changes