scmcp-shared 0.4.0__py3-none-any.whl → 0.5.0__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.
Files changed (171) hide show
  1. scmcp_shared/__init__.py +1 -3
  2. scmcp_shared/agent.py +58 -8
  3. scmcp_shared/backend.py +44 -0
  4. scmcp_shared/cli.py +75 -46
  5. scmcp_shared/kb.py +38 -0
  6. scmcp_shared/logging_config.py +6 -8
  7. scmcp_shared/mcp_base.py +184 -0
  8. scmcp_shared/schema/io.py +101 -59
  9. scmcp_shared/schema/pl.py +386 -490
  10. scmcp_shared/schema/pp.py +514 -265
  11. scmcp_shared/schema/preset/__init__.py +15 -0
  12. scmcp_shared/schema/preset/io.py +103 -0
  13. scmcp_shared/schema/preset/pl.py +843 -0
  14. scmcp_shared/schema/preset/pp.py +616 -0
  15. scmcp_shared/schema/preset/tl.py +917 -0
  16. scmcp_shared/schema/preset/util.py +123 -0
  17. scmcp_shared/schema/tl.py +355 -407
  18. scmcp_shared/schema/util.py +57 -72
  19. scmcp_shared/server/__init__.py +0 -12
  20. scmcp_shared/server/auto.py +10 -8
  21. scmcp_shared/server/code.py +3 -0
  22. scmcp_shared/server/preset/__init__.py +14 -0
  23. scmcp_shared/server/{io.py → preset/io.py} +26 -22
  24. scmcp_shared/server/{pl.py → preset/pl.py} +162 -78
  25. scmcp_shared/server/{pp.py → preset/pp.py} +123 -65
  26. scmcp_shared/server/{tl.py → preset/tl.py} +142 -79
  27. scmcp_shared/server/{util.py → preset/util.py} +123 -66
  28. scmcp_shared/util.py +109 -38
  29. scmcp_shared/vector_db/decoupler.lance/_transactions/0-9499b1b5-85d4-44c2-8f05-1bcce87fe4ef.txn +3 -0
  30. scmcp_shared/vector_db/decoupler.lance/_transactions/1-1632e7a3-4427-4077-8d03-57437144443d.txn +0 -0
  31. scmcp_shared/vector_db/decoupler.lance/_transactions/10-dcf66479-eafb-4193-9358-198154aea1c1.txn +0 -0
  32. scmcp_shared/vector_db/decoupler.lance/_transactions/11-2c6ddc17-49f5-47b5-8764-753297cf9e1b.txn +0 -0
  33. scmcp_shared/vector_db/decoupler.lance/_transactions/12-f079d0a2-9c1c-4e7a-abf6-3e3c4cddac11.txn +0 -0
  34. scmcp_shared/vector_db/decoupler.lance/_transactions/13-5bda9382-a06e-493d-85cb-e066172778ce.txn +0 -0
  35. scmcp_shared/vector_db/decoupler.lance/_transactions/14-6f9c669f-25e2-4096-b7ea-9b421a37e110.txn +0 -0
  36. scmcp_shared/vector_db/decoupler.lance/_transactions/15-2068cca9-31e8-45a3-86d1-bcb8924c72b9.txn +0 -0
  37. scmcp_shared/vector_db/decoupler.lance/_transactions/16-72356bb2-5c98-424e-97aa-a92fa3453da6.txn +0 -0
  38. scmcp_shared/vector_db/decoupler.lance/_transactions/17-9baa67ce-f6d3-478c-9511-20d01988d4d5.txn +0 -0
  39. scmcp_shared/vector_db/decoupler.lance/_transactions/18-b9f2e28e-c4c5-4ce7-bf58-402d53a39558.txn +0 -0
  40. scmcp_shared/vector_db/decoupler.lance/_transactions/19-d199d9f9-7990-4ec0-adde-e98c1c927202.txn +0 -0
  41. scmcp_shared/vector_db/decoupler.lance/_transactions/2-3827747c-095e-41cb-af69-3814bab3a588.txn +0 -0
  42. scmcp_shared/vector_db/decoupler.lance/_transactions/20-31c197a3-7a23-472f-a7e3-056c0ff11e3a.txn +0 -0
  43. scmcp_shared/vector_db/decoupler.lance/_transactions/21-066e3024-36f8-4557-83ae-d2f338ec045c.txn +0 -0
  44. scmcp_shared/vector_db/decoupler.lance/_transactions/22-1d1ccbe5-7c4c-4882-986a-c61ec2f7925e.txn +0 -0
  45. scmcp_shared/vector_db/decoupler.lance/_transactions/23-b2c41628-b2d6-49f1-81b5-3cd9100894b4.txn +0 -0
  46. scmcp_shared/vector_db/decoupler.lance/_transactions/24-e43e2e8d-9dd8-479f-b63c-d147e737c49f.txn +0 -0
  47. scmcp_shared/vector_db/decoupler.lance/_transactions/25-188708e9-5ee1-4b5c-8e13-45dec8efd60d.txn +0 -0
  48. scmcp_shared/vector_db/decoupler.lance/_transactions/26-4f4b6316-5680-4b31-8dd6-215cce66d7b5.txn +0 -0
  49. scmcp_shared/vector_db/decoupler.lance/_transactions/27-c1855f86-abab-44ef-9e61-1312dffc9b06.txn +0 -0
  50. scmcp_shared/vector_db/decoupler.lance/_transactions/28-650d2be0-e977-4177-b457-b733eea8b6ea.txn +0 -0
  51. scmcp_shared/vector_db/decoupler.lance/_transactions/29-e47751d8-0e44-46da-82bd-4836b00a8431.txn +0 -0
  52. scmcp_shared/vector_db/decoupler.lance/_transactions/3-518fc9b8-67de-48f7-94c8-f2398c63dbc5.txn +0 -0
  53. scmcp_shared/vector_db/decoupler.lance/_transactions/30-0db3ea0f-deca-4b5b-9d70-9fb5f741f90c.txn +0 -0
  54. scmcp_shared/vector_db/decoupler.lance/_transactions/31-ef76f0bb-bcfa-4031-b3ad-94b51ee818a9.txn +0 -0
  55. scmcp_shared/vector_db/decoupler.lance/_transactions/32-a763e0f1-5c8d-460f-a455-0c6f6c4f1450.txn +0 -0
  56. scmcp_shared/vector_db/decoupler.lance/_transactions/33-30bce2aa-8e6f-4f42-a323-c420133aa20f.txn +0 -0
  57. scmcp_shared/vector_db/decoupler.lance/_transactions/34-f91ec2f9-d34b-4fcf-8bc7-564c28e50538.txn +0 -0
  58. scmcp_shared/vector_db/decoupler.lance/_transactions/35-7f36a75c-96a7-4868-a4db-5d5f78ecf850.txn +0 -0
  59. scmcp_shared/vector_db/decoupler.lance/_transactions/36-f2df7f99-a37c-458a-958d-7eb5e81eee18.txn +0 -0
  60. scmcp_shared/vector_db/decoupler.lance/_transactions/37-e0af7415-955b-4167-8705-fa9ddb643e9a.txn +0 -0
  61. scmcp_shared/vector_db/decoupler.lance/_transactions/38-6c24a9f0-ce71-4dda-8193-479aa23c5456.txn +0 -0
  62. scmcp_shared/vector_db/decoupler.lance/_transactions/39-72b8a20c-3112-4cf1-8b05-b74a2c02c3f2.txn +0 -0
  63. scmcp_shared/vector_db/decoupler.lance/_transactions/4-42904942-5a79-4f28-90ce-35a4ae8c40d1.txn +0 -0
  64. scmcp_shared/vector_db/decoupler.lance/_transactions/40-95ac7526-6a2e-4914-9654-288c41bff370.txn +0 -0
  65. scmcp_shared/vector_db/decoupler.lance/_transactions/41-13430464-5e62-4aa8-9709-513693a75095.txn +0 -0
  66. scmcp_shared/vector_db/decoupler.lance/_transactions/42-cbb1ad83-a906-4540-bc37-4db158eac618.txn +0 -0
  67. scmcp_shared/vector_db/decoupler.lance/_transactions/43-3c246401-d742-49a9-b24d-cfc457685461.txn +0 -0
  68. scmcp_shared/vector_db/decoupler.lance/_transactions/44-11315c14-ecf4-4e3d-8690-46d57cb3e8c0.txn +0 -0
  69. scmcp_shared/vector_db/decoupler.lance/_transactions/45-7bbf4bc6-96d4-425a-afa2-34aec7121c85.txn +0 -0
  70. scmcp_shared/vector_db/decoupler.lance/_transactions/5-82dda0b4-7838-4f04-90f3-4b1e932c6891.txn +0 -0
  71. scmcp_shared/vector_db/decoupler.lance/_transactions/6-c78352d8-16ba-4814-bd7f-74b8c0c5efe7.txn +0 -0
  72. scmcp_shared/vector_db/decoupler.lance/_transactions/7-bb882b35-63f3-4c52-870f-6a64e3ac7f3c.txn +0 -0
  73. scmcp_shared/vector_db/decoupler.lance/_transactions/8-fc84ad1b-1b59-4822-8fc7-70f4eb18f6d9.txn +0 -0
  74. scmcp_shared/vector_db/decoupler.lance/_transactions/9-3404dcf1-bb17-40e6-9e5d-d9942dff90b2.txn +0 -0
  75. scmcp_shared/vector_db/decoupler.lance/_versions/1.manifest +0 -0
  76. scmcp_shared/vector_db/decoupler.lance/_versions/10.manifest +0 -0
  77. scmcp_shared/vector_db/decoupler.lance/_versions/11.manifest +0 -0
  78. scmcp_shared/vector_db/decoupler.lance/_versions/12.manifest +0 -0
  79. scmcp_shared/vector_db/decoupler.lance/_versions/13.manifest +0 -0
  80. scmcp_shared/vector_db/decoupler.lance/_versions/14.manifest +0 -0
  81. scmcp_shared/vector_db/decoupler.lance/_versions/15.manifest +0 -0
  82. scmcp_shared/vector_db/decoupler.lance/_versions/16.manifest +0 -0
  83. scmcp_shared/vector_db/decoupler.lance/_versions/17.manifest +0 -0
  84. scmcp_shared/vector_db/decoupler.lance/_versions/18.manifest +0 -0
  85. scmcp_shared/vector_db/decoupler.lance/_versions/19.manifest +0 -0
  86. scmcp_shared/vector_db/decoupler.lance/_versions/2.manifest +0 -0
  87. scmcp_shared/vector_db/decoupler.lance/_versions/20.manifest +0 -0
  88. scmcp_shared/vector_db/decoupler.lance/_versions/21.manifest +0 -0
  89. scmcp_shared/vector_db/decoupler.lance/_versions/22.manifest +0 -0
  90. scmcp_shared/vector_db/decoupler.lance/_versions/23.manifest +0 -0
  91. scmcp_shared/vector_db/decoupler.lance/_versions/24.manifest +0 -0
  92. scmcp_shared/vector_db/decoupler.lance/_versions/25.manifest +0 -0
  93. scmcp_shared/vector_db/decoupler.lance/_versions/26.manifest +0 -0
  94. scmcp_shared/vector_db/decoupler.lance/_versions/27.manifest +0 -0
  95. scmcp_shared/vector_db/decoupler.lance/_versions/28.manifest +0 -0
  96. scmcp_shared/vector_db/decoupler.lance/_versions/29.manifest +0 -0
  97. scmcp_shared/vector_db/decoupler.lance/_versions/3.manifest +0 -0
  98. scmcp_shared/vector_db/decoupler.lance/_versions/30.manifest +0 -0
  99. scmcp_shared/vector_db/decoupler.lance/_versions/31.manifest +0 -0
  100. scmcp_shared/vector_db/decoupler.lance/_versions/32.manifest +0 -0
  101. scmcp_shared/vector_db/decoupler.lance/_versions/33.manifest +0 -0
  102. scmcp_shared/vector_db/decoupler.lance/_versions/34.manifest +0 -0
  103. scmcp_shared/vector_db/decoupler.lance/_versions/35.manifest +0 -0
  104. scmcp_shared/vector_db/decoupler.lance/_versions/36.manifest +0 -0
  105. scmcp_shared/vector_db/decoupler.lance/_versions/37.manifest +0 -0
  106. scmcp_shared/vector_db/decoupler.lance/_versions/38.manifest +0 -0
  107. scmcp_shared/vector_db/decoupler.lance/_versions/39.manifest +0 -0
  108. scmcp_shared/vector_db/decoupler.lance/_versions/4.manifest +0 -0
  109. scmcp_shared/vector_db/decoupler.lance/_versions/40.manifest +0 -0
  110. scmcp_shared/vector_db/decoupler.lance/_versions/41.manifest +0 -0
  111. scmcp_shared/vector_db/decoupler.lance/_versions/42.manifest +0 -0
  112. scmcp_shared/vector_db/decoupler.lance/_versions/43.manifest +0 -0
  113. scmcp_shared/vector_db/decoupler.lance/_versions/44.manifest +0 -0
  114. scmcp_shared/vector_db/decoupler.lance/_versions/45.manifest +0 -0
  115. scmcp_shared/vector_db/decoupler.lance/_versions/46.manifest +0 -0
  116. scmcp_shared/vector_db/decoupler.lance/_versions/5.manifest +0 -0
  117. scmcp_shared/vector_db/decoupler.lance/_versions/6.manifest +0 -0
  118. scmcp_shared/vector_db/decoupler.lance/_versions/7.manifest +0 -0
  119. scmcp_shared/vector_db/decoupler.lance/_versions/8.manifest +0 -0
  120. scmcp_shared/vector_db/decoupler.lance/_versions/9.manifest +0 -0
  121. scmcp_shared/vector_db/decoupler.lance/data/0cc94dc3-2ca3-403c-a9df-59753f24b3f2.lance +0 -0
  122. scmcp_shared/vector_db/decoupler.lance/data/254a1a71-cdd2-4cca-b7ec-a50540fed62c.lance +0 -0
  123. scmcp_shared/vector_db/decoupler.lance/data/2574d216-5f05-4794-9e1c-986fafde6ab4.lance +0 -0
  124. scmcp_shared/vector_db/decoupler.lance/data/26c7bbe7-5f97-4453-b065-123b764448b3.lance +0 -0
  125. scmcp_shared/vector_db/decoupler.lance/data/286595a6-88f6-4b05-861e-e4f607a6fcdb.lance +0 -0
  126. scmcp_shared/vector_db/decoupler.lance/data/33219b1a-7575-46ef-bb64-2bdbde1e692b.lance +0 -0
  127. scmcp_shared/vector_db/decoupler.lance/data/344ad7dd-98bb-41de-b347-2f17bf5735cb.lance +0 -0
  128. scmcp_shared/vector_db/decoupler.lance/data/395b1ecb-68fe-4dd3-a770-4b3ed393ae0c.lance +0 -0
  129. scmcp_shared/vector_db/decoupler.lance/data/3db97f4c-9c35-44b7-9042-82b4006c5a22.lance +0 -0
  130. scmcp_shared/vector_db/decoupler.lance/data/4540246e-b0bb-4f4d-8f98-60a64f1c42ed.lance +0 -0
  131. scmcp_shared/vector_db/decoupler.lance/data/4643dbc0-9e45-4b63-81e1-e06cf9bddcec.lance +0 -0
  132. scmcp_shared/vector_db/decoupler.lance/data/4f28eb52-d409-43f2-ae17-d1826f209006.lance +0 -0
  133. scmcp_shared/vector_db/decoupler.lance/data/4fda4a22-35f0-4897-b4c5-6cedefba66e6.lance +0 -0
  134. scmcp_shared/vector_db/decoupler.lance/data/51ee77b6-ab24-44c0-916e-b81ff3912731.lance +0 -0
  135. scmcp_shared/vector_db/decoupler.lance/data/539d15c9-e88b-400c-9ab7-08f5e8dca10d.lance +0 -0
  136. scmcp_shared/vector_db/decoupler.lance/data/54007132-91f5-4909-8678-c471ef4d100f.lance +0 -0
  137. scmcp_shared/vector_db/decoupler.lance/data/546d88ec-0d5c-42bb-bccc-3271f3f183a4.lance +0 -0
  138. scmcp_shared/vector_db/decoupler.lance/data/6912ad8a-343c-4ca1-b1b7-4300125e688e.lance +0 -0
  139. scmcp_shared/vector_db/decoupler.lance/data/6b72e4f7-3051-40a4-a492-6d9eff1c647d.lance +0 -0
  140. scmcp_shared/vector_db/decoupler.lance/data/6d7ee320-ae1c-4e49-8ce5-c85971b11ce6.lance +0 -0
  141. scmcp_shared/vector_db/decoupler.lance/data/6ea47b70-69d4-43e9-b2c6-442fe50e4dd1.lance +0 -0
  142. scmcp_shared/vector_db/decoupler.lance/data/72adb5ed-bf11-4d06-b146-0272d333db08.lance +0 -0
  143. scmcp_shared/vector_db/decoupler.lance/data/745907df-e261-4f4b-a757-2c01c058bf27.lance +0 -0
  144. scmcp_shared/vector_db/decoupler.lance/data/78988307-4c66-4ad7-b295-7463ecd53609.lance +0 -0
  145. scmcp_shared/vector_db/decoupler.lance/data/798ce305-6d60-4f28-b82a-e1f647907abf.lance +0 -0
  146. scmcp_shared/vector_db/decoupler.lance/data/7c159cce-2741-442b-9c63-f44bf2996718.lance +0 -0
  147. scmcp_shared/vector_db/decoupler.lance/data/7cd7a818-e68b-4fa8-bad3-23b60c386670.lance +0 -0
  148. scmcp_shared/vector_db/decoupler.lance/data/7ec553ed-0c7a-4bac-99b2-2ad976b40466.lance +0 -0
  149. scmcp_shared/vector_db/decoupler.lance/data/83efdc85-d990-4762-b69a-fb1c3938f60f.lance +0 -0
  150. scmcp_shared/vector_db/decoupler.lance/data/8c1613b3-8d69-49c5-bfd0-a021bb516faf.lance +0 -0
  151. scmcp_shared/vector_db/decoupler.lance/data/95cd1b22-1f93-4133-9841-de21549ad8c5.lance +0 -0
  152. scmcp_shared/vector_db/decoupler.lance/data/9a2ea5d4-087e-4d3a-b64b-6c568b8a0010.lance +0 -0
  153. scmcp_shared/vector_db/decoupler.lance/data/b1c47dc6-450a-4dca-b465-badb6a3619c2.lance +0 -0
  154. scmcp_shared/vector_db/decoupler.lance/data/b21d183a-c51d-463b-932e-9beb2e0da9aa.lance +0 -0
  155. scmcp_shared/vector_db/decoupler.lance/data/b2598625-8683-4c33-be40-6f1a7555dc2c.lance +0 -0
  156. scmcp_shared/vector_db/decoupler.lance/data/b7297b39-1fc5-4886-be21-708b369bef59.lance +0 -0
  157. scmcp_shared/vector_db/decoupler.lance/data/b7d90085-5bd6-48f9-8a73-17eb7cf556fa.lance +0 -0
  158. scmcp_shared/vector_db/decoupler.lance/data/b988ceee-57fc-423b-8e67-5729086c6946.lance +0 -0
  159. scmcp_shared/vector_db/decoupler.lance/data/bfd68ea6-ddf4-44bb-aa87-2669f0462f7d.lance +0 -0
  160. scmcp_shared/vector_db/decoupler.lance/data/cb8ac58e-0e59-4391-95ab-6195e71b9625.lance +0 -0
  161. scmcp_shared/vector_db/decoupler.lance/data/d0f10434-afb5-49c5-9e77-d39a4f8cca94.lance +0 -0
  162. scmcp_shared/vector_db/decoupler.lance/data/d3f89fec-5795-4e11-8c15-bc2206a7fae2.lance +0 -0
  163. scmcp_shared/vector_db/decoupler.lance/data/e063c8a4-5ef1-4933-a049-b41049d9be5f.lance +0 -0
  164. scmcp_shared/vector_db/decoupler.lance/data/e2348b24-f290-4fe2-a6c8-e98009ae4c1b.lance +0 -0
  165. scmcp_shared/vector_db/decoupler.lance/data/e5d3f893-6763-40dc-9d02-04e2f56a4883.lance +0 -0
  166. {scmcp_shared-0.4.0.dist-info → scmcp_shared-0.5.0.dist-info}/METADATA +2 -1
  167. scmcp_shared-0.5.0.dist-info/RECORD +171 -0
  168. scmcp_shared/server/base.py +0 -148
  169. scmcp_shared-0.4.0.dist-info/RECORD +0 -24
  170. {scmcp_shared-0.4.0.dist-info → scmcp_shared-0.5.0.dist-info}/WHEEL +0 -0
  171. {scmcp_shared-0.4.0.dist-info → scmcp_shared-0.5.0.dist-info}/licenses/LICENSE +0 -0
@@ -1,20 +1,28 @@
1
- import os
2
- import inspect
3
1
  import scanpy as sc
4
- from fastmcp import FastMCP, Context
5
2
  from fastmcp.tools.tool import Tool
6
3
  from fastmcp.exceptions import ToolError
7
- from ..schema.pp import *
8
- from ..schema import AdataInfo
9
- from ..util import filter_args, add_op_log, forward_request, get_ads, generate_msg
10
- from .base import BaseMCP
4
+ from scmcp_shared.schema.preset import AdataInfo
5
+ from scmcp_shared.schema.preset.pp import *
6
+ from scmcp_shared.util import (
7
+ filter_args,
8
+ add_op_log,
9
+ forward_request,
10
+ get_ads,
11
+ generate_msg,
12
+ )
13
+ from scmcp_shared.mcp_base import BaseMCP
11
14
 
12
15
 
13
16
  class ScanpyPreprocessingMCP(BaseMCP):
14
- def __init__(self, include_tools: list = None, exclude_tools: list = None, AdataInfo: AdataInfo = AdataInfo):
17
+ def __init__(
18
+ self,
19
+ include_tools: list = None,
20
+ exclude_tools: list = None,
21
+ AdataInfo: AdataInfo = AdataInfo,
22
+ ):
15
23
  """
16
24
  Initialize ScanpyPreprocessingMCP with optional tool filtering.
17
-
25
+
18
26
  Args:
19
27
  include_tools (list, optional): List of tool names to include. If None, all tools are included.
20
28
  exclude_tools (list, optional): List of tool names to exclude. If None, no tools are excluded.
@@ -23,7 +31,9 @@ class ScanpyPreprocessingMCP(BaseMCP):
23
31
  super().__init__("ScanpyMCP-PP-Server", include_tools, exclude_tools, AdataInfo)
24
32
 
25
33
  def _tool_subset_cells(self):
26
- def _subset_cells(request: SubsetCellParams, adinfo: self.AdataInfo=self.AdataInfo()):
34
+ def _subset_cells(
35
+ request: SubsetCellParam, adinfo: self.AdataInfo = self.AdataInfo()
36
+ ):
27
37
  """filter or subset cells based on total genes expressed counts and numbers. or values in adata.obs[obs_key]"""
28
38
  try:
29
39
  result = forward_request("subset_cells", request, adinfo)
@@ -39,34 +49,44 @@ class ScanpyPreprocessingMCP(BaseMCP):
39
49
  # Subset based on obs (cells) criteria
40
50
  if request.obs_key is not None:
41
51
  if request.obs_key not in adata.obs.columns:
42
- raise ValueError(f"Key '{request.obs_key}' not found in adata.obs")
52
+ raise ValueError(
53
+ f"Key '{request.obs_key}' not found in adata.obs"
54
+ )
43
55
  mask = True # Start with all cells selected
44
56
  if request.obs_value is not None:
45
57
  mask = mask & (adata.obs[request.obs_key] == request.obs_value)
46
58
  if request.obs_min is not None:
47
- mask = mask & (adata.obs[request.obs_key] >= request.obs_min)
59
+ mask = mask & (adata.obs[request.obs_key] >= request.obs_min)
48
60
  if request.obs_max is not None:
49
- mask = mask & (adata.obs[request.obs_key] <= request.obs_max)
61
+ mask = mask & (adata.obs[request.obs_key] <= request.obs_max)
50
62
  adata = adata[mask, :]
51
- add_op_log(adata, "subset_cells",
63
+ add_op_log(
64
+ adata,
65
+ "subset_cells",
52
66
  {
53
- "obs_key": request.obs_key, "obs_value": request.obs_value,
54
- "obs_min": request.obs_min, "obs_max": request.obs_max
55
- }, adinfo
67
+ "obs_key": request.obs_key,
68
+ "obs_value": request.obs_value,
69
+ "obs_min": request.obs_min,
70
+ "obs_max": request.obs_max,
71
+ },
72
+ adinfo,
56
73
  )
57
74
  ads.set_adata(adata, adinfo=adinfo)
58
75
  return [generate_msg(adinfo, adata, ads)]
59
76
  except ToolError as e:
60
77
  raise ToolError(e)
61
78
  except Exception as e:
62
- if hasattr(e, '__context__') and e.__context__:
79
+ if hasattr(e, "__context__") and e.__context__:
63
80
  raise ToolError(e.__context__)
64
81
  else:
65
82
  raise ToolError(e)
66
- return Tool.from_function(_subset_cells, name="subset_cells")
83
+
84
+ return Tool.from_function(_subset_cells, name="subset_cells", enabled=True)
67
85
 
68
86
  def _tool_subset_genes(self):
69
- def _subset_genes(request: SubsetGeneParams, adinfo: self.AdataInfo=self.AdataInfo()):
87
+ def _subset_genes(
88
+ request: SubsetGeneParam, adinfo: self.AdataInfo = self.AdataInfo()
89
+ ):
70
90
  """filter or subset genes based on number of cells or counts, or values in adata.var[var_key] or subset highly variable genes"""
71
91
  try:
72
92
  result = forward_request("pp_subset_genes", request, adinfo)
@@ -77,40 +97,48 @@ class ScanpyPreprocessingMCP(BaseMCP):
77
97
  adata = ads.get_adata(adinfo=adinfo).copy()
78
98
  if request.highly_variable:
79
99
  adata = adata[:, adata.var.highly_variable]
80
- add_op_log(adata, "subset_genes",
81
- {"hpv": "true"}, adinfo
82
- )
100
+ add_op_log(adata, "subset_genes", {"hpv": "true"}, adinfo)
83
101
  if func_kwargs:
84
102
  sc.pp.filter_genes(adata, **func_kwargs)
85
103
  add_op_log(adata, sc.pp.filter_genes, func_kwargs, adinfo)
86
104
  if request.var_key is not None:
87
105
  if request.var_key not in adata.var.columns:
88
- raise ValueError(f"Key '{request.var_key}' not found in adata.var")
106
+ raise ValueError(
107
+ f"Key '{request.var_key}' not found in adata.var"
108
+ )
89
109
  mask = True # Start with all genes selected
90
110
  if request.var_min is not None:
91
111
  mask = mask & (adata.var[request.var_key] >= request.var_min)
92
112
  if request.var_max is not None:
93
- mask = mask & (adata.var[request.var_key] <= request.var_max)
113
+ mask = mask & (adata.var[request.var_key] <= request.var_max)
94
114
  adata = adata[:, mask]
95
- add_op_log(adata, "subset_genes",
115
+ add_op_log(
116
+ adata,
117
+ "subset_genes",
96
118
  {
97
- "var_key": request.var_key, "var_min": request.var_min, "var_max": request.var_max,
98
- "hpv": request.highly_variable
99
- }, adinfo
119
+ "var_key": request.var_key,
120
+ "var_min": request.var_min,
121
+ "var_max": request.var_max,
122
+ "hpv": request.highly_variable,
123
+ },
124
+ adinfo,
100
125
  )
101
126
  ads.set_adata(adata, adinfo=adinfo)
102
127
  return [generate_msg(adinfo, adata, ads)]
103
128
  except ToolError as e:
104
129
  raise ToolError(e)
105
130
  except Exception as e:
106
- if hasattr(e, '__context__') and e.__context__:
131
+ if hasattr(e, "__context__") and e.__context__:
107
132
  raise ToolError(e.__context__)
108
133
  else:
109
134
  raise ToolError(e)
110
- return Tool.from_function(_subset_genes, name="subset_genes")
135
+
136
+ return Tool.from_function(_subset_genes, name="subset_genes", enabled=True)
111
137
 
112
138
  def _tool_calculate_qc_metrics(self):
113
- def _calculate_qc_metrics(request: CalculateQCMetrics, adinfo: self.AdataInfo=self.AdataInfo()):
139
+ def _calculate_qc_metrics(
140
+ request: CalculateQCMetrics, adinfo: self.AdataInfo = self.AdataInfo()
141
+ ):
114
142
  """Calculate quality control metrics(common metrics: total counts, gene number, percentage of counts in ribosomal and mitochondrial) for AnnData."""
115
143
  try:
116
144
  result = forward_request("pp_calculate_qc_metrics", request, adinfo)
@@ -129,19 +157,27 @@ class ScanpyPreprocessingMCP(BaseMCP):
129
157
  sc.pp.calculate_qc_metrics(adata, **func_kwargs)
130
158
  add_op_log(adata, sc.pp.calculate_qc_metrics, func_kwargs, adinfo)
131
159
  except KeyError as e:
132
- raise KeyError(f"Cound find {e} in adata.var, consider to use mark_var tool to mark the variable")
160
+ raise KeyError(
161
+ f"Cound find {e} in adata.var, consider to use mark_var tool to mark the variable"
162
+ )
133
163
  return [generate_msg(adinfo, adata, ads)]
134
164
  except ToolError as e:
135
165
  raise ToolError(e)
136
166
  except Exception as e:
137
- if hasattr(e, '__context__') and e.__context__:
167
+ if hasattr(e, "__context__") and e.__context__:
138
168
  raise ToolError(e.__context__)
139
169
  else:
140
170
  raise ToolError(e)
141
- return Tool.from_function(_calculate_qc_metrics, name="calculate_qc_metrics")
171
+
172
+ return Tool.from_function(
173
+ _calculate_qc_metrics, name="calculate_qc_metrics", enabled=True
174
+ )
142
175
 
143
176
  def _tool_log1p(self):
144
- def _log1p(request: Log1PParams=Log1PParams(), adinfo: self.AdataInfo=self.AdataInfo()):
177
+ def _log1p(
178
+ request: Log1PParam = Log1PParam(),
179
+ adinfo: self.AdataInfo = self.AdataInfo(),
180
+ ):
145
181
  """Logarithmize the data matrix"""
146
182
  try:
147
183
  result = forward_request("pp_log1p", request, adinfo)
@@ -161,14 +197,17 @@ class ScanpyPreprocessingMCP(BaseMCP):
161
197
  except ToolError as e:
162
198
  raise ToolError(e)
163
199
  except Exception as e:
164
- if hasattr(e, '__context__') and e.__context__:
200
+ if hasattr(e, "__context__") and e.__context__:
165
201
  raise ToolError(e.__context__)
166
202
  else:
167
203
  raise ToolError(e)
168
- return Tool.from_function(_log1p, name="log1p")
204
+
205
+ return Tool.from_function(_log1p, name="log1p", enabled=True)
169
206
 
170
207
  def _tool_normalize_total(self):
171
- def _normalize_total(request: NormalizeTotalParams, adinfo: self.AdataInfo=self.AdataInfo()):
208
+ def _normalize_total(
209
+ request: NormalizeTotalParam, adinfo: self.AdataInfo = self.AdataInfo()
210
+ ):
172
211
  """Normalize counts per cell to the same total count"""
173
212
  try:
174
213
  result = forward_request("pp_normalize_total", request, adinfo)
@@ -184,20 +223,25 @@ class ScanpyPreprocessingMCP(BaseMCP):
184
223
  except ToolError as e:
185
224
  raise ToolError(e)
186
225
  except Exception as e:
187
- if hasattr(e, '__context__') and e.__context__:
226
+ if hasattr(e, "__context__") and e.__context__:
188
227
  raise ToolError(e.__context__)
189
228
  else:
190
229
  raise ToolError(e)
191
- return Tool.from_function(_normalize_total, name="normalize_total")
230
+
231
+ return Tool.from_function(
232
+ _normalize_total, name="normalize_total", enabled=True
233
+ )
192
234
 
193
235
  def _tool_highly_variable_genes(self):
194
- def _highly_variable_genes(request: HighlyVariableGenesParams, adinfo: self.AdataInfo=self.AdataInfo()):
236
+ def _highly_variable_genes(
237
+ request: HighlyVariableGenesParam, adinfo: self.AdataInfo = self.AdataInfo()
238
+ ):
195
239
  """Annotate highly variable genes"""
196
240
  try:
197
241
  result = forward_request("pp_highly_variable_genes", request, adinfo)
198
242
  if result is not None:
199
243
  return result
200
- try:
244
+ try:
201
245
  func_kwargs = filter_args(request, sc.pp.highly_variable_genes)
202
246
  ads = get_ads()
203
247
  adata = ads.get_adata(adinfo=adinfo)
@@ -209,19 +253,24 @@ class ScanpyPreprocessingMCP(BaseMCP):
209
253
  except ToolError as e:
210
254
  raise ToolError(e)
211
255
  except Exception as e:
212
- if hasattr(e, '__context__') and e.__context__:
256
+ if hasattr(e, "__context__") and e.__context__:
213
257
  raise ToolError(e.__context__)
214
258
  else:
215
259
  raise ToolError(e)
216
- return Tool.from_function(_highly_variable_genes, name="highly_variable_genes")
260
+
261
+ return Tool.from_function(
262
+ _highly_variable_genes, name="highly_variable_genes", enabled=True
263
+ )
217
264
 
218
265
  def _tool_regress_out(self):
219
- def _regress_out(request: RegressOutParams, adinfo: self.AdataInfo=self.AdataInfo()):
266
+ def _regress_out(
267
+ request: RegressOutParam, adinfo: self.AdataInfo = self.AdataInfo()
268
+ ):
220
269
  """Regress out (mostly) unwanted sources of variation."""
221
270
  try:
222
271
  result = forward_request("pp_regress_out", request, adinfo)
223
272
  if result is not None:
224
- return result
273
+ return result
225
274
  func_kwargs = filter_args(request, sc.pp.regress_out)
226
275
  ads = get_ads()
227
276
  adata = ads.get_adata(adinfo=adinfo).copy()
@@ -232,44 +281,46 @@ class ScanpyPreprocessingMCP(BaseMCP):
232
281
  except ToolError as e:
233
282
  raise ToolError(e)
234
283
  except Exception as e:
235
- if hasattr(e, '__context__') and e.__context__:
284
+ if hasattr(e, "__context__") and e.__context__:
236
285
  raise ToolError(e.__context__)
237
286
  else:
238
287
  raise ToolError(e)
239
- return Tool.from_function(_regress_out, name="regress_out")
288
+
289
+ return Tool.from_function(_regress_out, name="regress_out", enabled=True)
240
290
 
241
291
  def _tool_scale(self):
242
- def _scale(request: ScaleParams, adinfo: self.AdataInfo=self.AdataInfo()):
292
+ def _scale(request: ScaleParam, adinfo: self.AdataInfo = self.AdataInfo()):
243
293
  """Scale data to unit variance and zero mean"""
244
294
  try:
245
295
  result = forward_request("pp_scale", request, adinfo)
246
296
  if result is not None:
247
- return result
297
+ return result
248
298
  func_kwargs = filter_args(request, sc.pp.scale)
249
299
  ads = get_ads()
250
300
  adata = ads.get_adata(adinfo=adinfo).copy()
251
301
 
252
302
  sc.pp.scale(adata, **func_kwargs)
253
303
  add_op_log(adata, sc.pp.scale, func_kwargs, adinfo)
254
-
304
+
255
305
  ads.set_adata(adata, adinfo=adinfo)
256
306
  return [generate_msg(adinfo, adata, ads)]
257
307
  except ToolError as e:
258
308
  raise ToolError(e)
259
309
  except Exception as e:
260
- if hasattr(e, '__context__') and e.__context__:
310
+ if hasattr(e, "__context__") and e.__context__:
261
311
  raise ToolError(e.__context__)
262
312
  else:
263
313
  raise ToolError(e)
264
- return Tool.from_function(_scale, name="scale")
314
+
315
+ return Tool.from_function(_scale, name="scale", enabled=True)
265
316
 
266
317
  def _tool_combat(self):
267
- def _combat(request: CombatParams, adinfo: self.AdataInfo=self.AdataInfo()):
318
+ def _combat(request: CombatParam, adinfo: self.AdataInfo = self.AdataInfo()):
268
319
  """ComBat function for batch effect correction"""
269
320
  try:
270
321
  result = forward_request("pp_combat", request, adinfo)
271
322
  if result is not None:
272
- return result
323
+ return result
273
324
  func_kwargs = filter_args(request, sc.pp.combat)
274
325
  ads = get_ads()
275
326
  adata = ads.get_adata(adinfo=adinfo).copy()
@@ -282,19 +333,22 @@ class ScanpyPreprocessingMCP(BaseMCP):
282
333
  except ToolError as e:
283
334
  raise ToolError(e)
284
335
  except Exception as e:
285
- if hasattr(e, '__context__') and e.__context__:
336
+ if hasattr(e, "__context__") and e.__context__:
286
337
  raise ToolError(e.__context__)
287
338
  else:
288
339
  raise ToolError(e)
289
- return Tool.from_function(_combat, name="combat")
340
+
341
+ return Tool.from_function(_combat, name="combat", enabled=True)
290
342
 
291
343
  def _tool_scrublet(self):
292
- def _scrublet(request: ScrubletParams, adinfo: self.AdataInfo=self.AdataInfo()):
344
+ def _scrublet(
345
+ request: ScrubletParam, adinfo: self.AdataInfo = self.AdataInfo()
346
+ ):
293
347
  """Predict doublets using Scrublet"""
294
348
  try:
295
349
  result = forward_request("pp_scrublet", request, adinfo)
296
350
  if result is not None:
297
- return result
351
+ return result
298
352
  func_kwargs = filter_args(request, sc.pp.scrublet)
299
353
  ads = get_ads()
300
354
  adata = ads.get_adata(adinfo=adinfo)
@@ -304,14 +358,17 @@ class ScanpyPreprocessingMCP(BaseMCP):
304
358
  except ToolError as e:
305
359
  raise ToolError(e)
306
360
  except Exception as e:
307
- if hasattr(e, '__context__') and e.__context__:
361
+ if hasattr(e, "__context__") and e.__context__:
308
362
  raise ToolError(e.__context__)
309
363
  else:
310
364
  raise ToolError(e)
311
- return Tool.from_function(_scrublet, name="scrublet")
365
+
366
+ return Tool.from_function(_scrublet, name="scrublet", enabled=True)
312
367
 
313
368
  def _tool_neighbors(self):
314
- def _neighbors(request: NeighborsParams, adinfo: self.AdataInfo=self.AdataInfo()):
369
+ def _neighbors(
370
+ request: NeighborsParam, adinfo: self.AdataInfo = self.AdataInfo()
371
+ ):
315
372
  """Compute nearest neighbors distance matrix and neighborhood graph"""
316
373
  try:
317
374
  result = forward_request("pp_neighbors", request, adinfo)
@@ -326,8 +383,9 @@ class ScanpyPreprocessingMCP(BaseMCP):
326
383
  except ToolError as e:
327
384
  raise ToolError(e)
328
385
  except Exception as e:
329
- if hasattr(e, '__context__') and e.__context__:
386
+ if hasattr(e, "__context__") and e.__context__:
330
387
  raise ToolError(e.__context__)
331
388
  else:
332
389
  raise ToolError(e)
333
- return Tool.from_function(_neighbors, name="neighbors")
390
+
391
+ return Tool.from_function(_neighbors, name="neighbors", enabled=True)