codeocean-mcp-server 0.1.0__tar.gz → 0.3.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.
Files changed (23) hide show
  1. {codeocean_mcp_server-0.1.0 → codeocean_mcp_server-0.3.0}/.gitignore +8 -0
  2. codeocean_mcp_server-0.3.0/CHANGELOG.md +15 -0
  3. {codeocean_mcp_server-0.1.0 → codeocean_mcp_server-0.3.0}/PKG-INFO +14 -8
  4. {codeocean_mcp_server-0.1.0 → codeocean_mcp_server-0.3.0}/README.md +12 -6
  5. {codeocean_mcp_server-0.1.0 → codeocean_mcp_server-0.3.0}/pyproject.toml +2 -2
  6. {codeocean_mcp_server-0.1.0 → codeocean_mcp_server-0.3.0}/src/codeocean_mcp_server/server.py +2 -1
  7. {codeocean_mcp_server-0.1.0 → codeocean_mcp_server-0.3.0}/src/codeocean_mcp_server/tools/capsules.py +12 -20
  8. {codeocean_mcp_server-0.1.0 → codeocean_mcp_server-0.3.0}/src/codeocean_mcp_server/tools/computations.py +13 -21
  9. {codeocean_mcp_server-0.1.0 → codeocean_mcp_server-0.3.0}/src/codeocean_mcp_server/tools/data_assets.py +15 -31
  10. {codeocean_mcp_server-0.1.0 → codeocean_mcp_server-0.3.0}/tests/test_multi_tool_calling.py +1 -1
  11. {codeocean_mcp_server-0.1.0 → codeocean_mcp_server-0.3.0}/tests/test_tool_calling.py +1 -1
  12. {codeocean_mcp_server-0.1.0 → codeocean_mcp_server-0.3.0}/uv.lock +5 -5
  13. codeocean_mcp_server-0.1.0/CHANGELOG.md +0 -6
  14. {codeocean_mcp_server-0.1.0 → codeocean_mcp_server-0.3.0}/.python-version +0 -0
  15. {codeocean_mcp_server-0.1.0 → codeocean_mcp_server-0.3.0}/LICENSE +0 -0
  16. {codeocean_mcp_server-0.1.0 → codeocean_mcp_server-0.3.0}/RELEASE.md +0 -0
  17. {codeocean_mcp_server-0.1.0 → codeocean_mcp_server-0.3.0}/src/codeocean_mcp_server/__init__.py +0 -0
  18. {codeocean_mcp_server-0.1.0 → codeocean_mcp_server-0.3.0}/src/codeocean_mcp_server/file_utils.py +0 -0
  19. {codeocean_mcp_server-0.1.0 → codeocean_mcp_server-0.3.0}/src/codeocean_mcp_server/models.py +0 -0
  20. {codeocean_mcp_server-0.1.0 → codeocean_mcp_server-0.3.0}/src/codeocean_mcp_server/tools/__init__.py +0 -0
  21. {codeocean_mcp_server-0.1.0 → codeocean_mcp_server-0.3.0}/tests/bedrock_call.py +0 -0
  22. {codeocean_mcp_server-0.1.0 → codeocean_mcp_server-0.3.0}/tests/bedrock_tools_converter.py +0 -0
  23. {codeocean_mcp_server-0.1.0 → codeocean_mcp_server-0.3.0}/tests/mcp_client.py +0 -0
@@ -172,3 +172,11 @@ cython_debug/
172
172
 
173
173
  # PyPI configuration file
174
174
  .pypirc
175
+
176
+ # macOS
177
+ .DS_Store
178
+ *.DS_Store
179
+
180
+ # CI
181
+ .cci_pycache/
182
+ .temp-python-version
@@ -0,0 +1,15 @@
1
+ CHANGELOG
2
+ =========
3
+
4
+ ## 0.3.0 (2025-07-14)
5
+
6
+ - [#5](https://github.com/codeocean/codeocean-mcp-server/pull/5) feat: Add support for AI agent ID in server configuration
7
+ - [#4](https://github.com/codeocean/codeocean-mcp-server/pull/4) fix: ignore CI artifacts in sdist
8
+
9
+ ## 0.2.0 (2025-07-02)
10
+
11
+ - [#2](https://github.com/codeocean/codeocean-mcp-server/pull/2) fix: return native client objects instead of Pydantic models
12
+
13
+ ## 0.1.0 (2025-07-01)
14
+
15
+ - [#1](https://github.com/codeocean/codeocean-mcp-server/pull/1) Initial version
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: codeocean-mcp-server
3
- Version: 0.1.0
3
+ Version: 0.3.0
4
4
  Summary: Code Ocean MCP Server
5
5
  Project-URL: Homepage, https://github.com/codeocean/codeocean-mcp-server
6
6
  Project-URL: Issues, https://github.com/codeocean/codeocean-mcp-server/issues
@@ -12,7 +12,7 @@ Classifier: License :: OSI Approved :: MIT License
12
12
  Classifier: Operating System :: OS Independent
13
13
  Classifier: Programming Language :: Python :: 3
14
14
  Requires-Python: >=3.10
15
- Requires-Dist: codeocean>=0.7.0
15
+ Requires-Dist: codeocean<0.9.0,>=0.8.0
16
16
  Requires-Dist: fastmcp>=2.9.2
17
17
  Description-Content-Type: text/markdown
18
18
 
@@ -63,7 +63,8 @@ Here's an example VS Code MCP server configuration:
63
63
  "args": ["codeocean-mcp-server"],
64
64
  "env": {
65
65
  "CODEOCEAN_DOMAIN": "https://codeocean.acme.com",
66
- "CODEOCEAN_TOKEN": "${input:codeocean-token}"
66
+ "CODEOCEAN_TOKEN": "${input:codeocean-token}",
67
+ "AGENT_ID": "VS Code"
67
68
  }
68
69
  }
69
70
  },
@@ -88,7 +89,8 @@ Here's an example VS Code MCP server configuration:
88
89
  "args": ["codeocean-mcp-server"],
89
90
  "env": {
90
91
  "CODEOCEAN_DOMAIN": "https://codeocean.acme.com",
91
- "CODEOCEAN_TOKEN": "<YOUR_API_KEY>"
92
+ "CODEOCEAN_TOKEN": "<YOUR_API_KEY>",
93
+ "AGENT_ID": "Claude Desktop"
92
94
  }
93
95
  }
94
96
  }
@@ -111,7 +113,8 @@ Cline stores all of its MCP settings in a JSON file called cline_mcp_settings.js
111
113
  "args": ["codeocean-mcp-server"],
112
114
  "env": {
113
115
  "CODEOCEAN_DOMAIN": "https://codeocean.acme.com",
114
- "CODEOCEAN_TOKEN": "<YOUR_API_KEY>"
116
+ "CODEOCEAN_TOKEN": "<YOUR_API_KEY>",
117
+ "AGENT_ID": "Cline"
115
118
  },
116
119
  "alwaysAllow": [], // optional: list of tools to auto-approve
117
120
  "disabled": false // ensure it’s enabled
@@ -140,7 +143,8 @@ Roo Code’s MCP support is configured globally across all workspaces via a JSON
140
143
  "args": ["codeocean-mcp-server"],
141
144
  "env": {
142
145
  "CODEOCEAN_DOMAIN": "https://codeocean.acme.com",
143
- "CODEOCEAN_TOKEN": "<YOUR_API_KEY>"
146
+ "CODEOCEAN_TOKEN": "<YOUR_API_KEY>",
147
+ "AGENT_ID": "Roo Code"
144
148
  }
145
149
  }
146
150
  }
@@ -168,7 +172,8 @@ Cursor stores MCP servers in a JSON file at either ~/.cursor/mcp.json (global) o
168
172
  "args": ["codeocean-mcp-server"],
169
173
  "env": {
170
174
  "CODEOCEAN_DOMAIN": "https://codeocean.acme.com",
171
- "CODEOCEAN_TOKEN": "<YOUR_API_KEY>"
175
+ "CODEOCEAN_TOKEN": "<YOUR_API_KEY>",
176
+ "AGENT_ID": "Cursor"
172
177
  }
173
178
  }
174
179
  }
@@ -191,7 +196,8 @@ Windsurf (Cascade) uses mcp_config.json under ~/.codeium/windsurf/ (or via the C
191
196
  "args": ["codeocean-mcp-server"],
192
197
  "env": {
193
198
  "CODEOCEAN_DOMAIN": "https://codeocean.acme.com",
194
- "CODEOCEAN_TOKEN": "<YOUR_API_KEY>"
199
+ "CODEOCEAN_TOKEN": "<YOUR_API_KEY>",
200
+ "AGENT_ID": "Windsurf"
195
201
  }
196
202
  }
197
203
  }
@@ -45,7 +45,8 @@ Here's an example VS Code MCP server configuration:
45
45
  "args": ["codeocean-mcp-server"],
46
46
  "env": {
47
47
  "CODEOCEAN_DOMAIN": "https://codeocean.acme.com",
48
- "CODEOCEAN_TOKEN": "${input:codeocean-token}"
48
+ "CODEOCEAN_TOKEN": "${input:codeocean-token}",
49
+ "AGENT_ID": "VS Code"
49
50
  }
50
51
  }
51
52
  },
@@ -70,7 +71,8 @@ Here's an example VS Code MCP server configuration:
70
71
  "args": ["codeocean-mcp-server"],
71
72
  "env": {
72
73
  "CODEOCEAN_DOMAIN": "https://codeocean.acme.com",
73
- "CODEOCEAN_TOKEN": "<YOUR_API_KEY>"
74
+ "CODEOCEAN_TOKEN": "<YOUR_API_KEY>",
75
+ "AGENT_ID": "Claude Desktop"
74
76
  }
75
77
  }
76
78
  }
@@ -93,7 +95,8 @@ Cline stores all of its MCP settings in a JSON file called cline_mcp_settings.js
93
95
  "args": ["codeocean-mcp-server"],
94
96
  "env": {
95
97
  "CODEOCEAN_DOMAIN": "https://codeocean.acme.com",
96
- "CODEOCEAN_TOKEN": "<YOUR_API_KEY>"
98
+ "CODEOCEAN_TOKEN": "<YOUR_API_KEY>",
99
+ "AGENT_ID": "Cline"
97
100
  },
98
101
  "alwaysAllow": [], // optional: list of tools to auto-approve
99
102
  "disabled": false // ensure it’s enabled
@@ -122,7 +125,8 @@ Roo Code’s MCP support is configured globally across all workspaces via a JSON
122
125
  "args": ["codeocean-mcp-server"],
123
126
  "env": {
124
127
  "CODEOCEAN_DOMAIN": "https://codeocean.acme.com",
125
- "CODEOCEAN_TOKEN": "<YOUR_API_KEY>"
128
+ "CODEOCEAN_TOKEN": "<YOUR_API_KEY>",
129
+ "AGENT_ID": "Roo Code"
126
130
  }
127
131
  }
128
132
  }
@@ -150,7 +154,8 @@ Cursor stores MCP servers in a JSON file at either ~/.cursor/mcp.json (global) o
150
154
  "args": ["codeocean-mcp-server"],
151
155
  "env": {
152
156
  "CODEOCEAN_DOMAIN": "https://codeocean.acme.com",
153
- "CODEOCEAN_TOKEN": "<YOUR_API_KEY>"
157
+ "CODEOCEAN_TOKEN": "<YOUR_API_KEY>",
158
+ "AGENT_ID": "Cursor"
154
159
  }
155
160
  }
156
161
  }
@@ -173,7 +178,8 @@ Windsurf (Cascade) uses mcp_config.json under ~/.codeium/windsurf/ (or via the C
173
178
  "args": ["codeocean-mcp-server"],
174
179
  "env": {
175
180
  "CODEOCEAN_DOMAIN": "https://codeocean.acme.com",
176
- "CODEOCEAN_TOKEN": "<YOUR_API_KEY>"
181
+ "CODEOCEAN_TOKEN": "<YOUR_API_KEY>",
182
+ "AGENT_ID": "Windsurf"
177
183
  }
178
184
  }
179
185
  }
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "codeocean-mcp-server"
3
- version = "0.1.0"
3
+ version = "0.3.0"
4
4
  authors = [{ name = "Code Ocean", email = "dev@codeocean.com" }]
5
5
  description = "Code Ocean MCP Server"
6
6
  readme = "README.md"
@@ -11,7 +11,7 @@ classifiers = [
11
11
  "Operating System :: OS Independent",
12
12
  ]
13
13
  dependencies = [
14
- "codeocean>=0.7.0",
14
+ "codeocean>=0.8.0,<0.9.0",
15
15
  "fastmcp>=2.9.2",
16
16
  ]
17
17
  license = "MIT"
@@ -15,7 +15,8 @@ def main():
15
15
  "Environment variables CODEOCEAN_DOMAIN and "
16
16
  "CODEOCEAN_TOKEN must be set."
17
17
  )
18
- client = CodeOcean(domain=domain, token=token)
18
+ agent_id = os.getenv("AGENT_ID", "AI Agent")
19
+ client = CodeOcean(domain=domain, token=token, agent_id=agent_id)
19
20
 
20
21
  mcp = FastMCP(
21
22
  name="Code Ocean",
@@ -11,12 +11,8 @@ from mcp.server.fastmcp import FastMCP
11
11
 
12
12
  from codeocean_mcp_server.models import dataclass_to_pydantic
13
13
 
14
- CapsuleModel = dataclass_to_pydantic(Capsule)
15
14
  CapsuleSearchParamsModel = dataclass_to_pydantic(CapsuleSearchParams)
16
- CapsuleSearchResultsModel = dataclass_to_pydantic(CapsuleSearchResults)
17
- ComputationModel = dataclass_to_pydantic(Computation)
18
15
  DataAssetAttachParamsModel = dataclass_to_pydantic(DataAssetAttachParams)
19
- DataAssetAttachResultsModel = dataclass_to_pydantic(DataAssetAttachResults)
20
16
 
21
17
 
22
18
  def add_tools(mcp: FastMCP, client: CodeOcean):
@@ -31,12 +27,10 @@ def add_tools(mcp: FastMCP, client: CodeOcean):
31
27
  "like sort_by or sort_order unless requested."
32
28
  )
33
29
  )
34
- def search_capsules(
35
- search_params: CapsuleSearchParamsModel,
36
- ) -> CapsuleSearchResultsModel:
30
+ def search_capsules(search_params: CapsuleSearchParamsModel) -> CapsuleSearchResults:
37
31
  """Search for capsules matching specified criteria."""
38
32
  params = CapsuleSearchParams(**search_params.model_dump(exclude_none=True))
39
- return dataclass_to_pydantic(client.capsules.search_capsules(params))
33
+ return client.capsules.search_capsules(params)
40
34
 
41
35
  @mcp.tool(
42
36
  description=(
@@ -47,13 +41,14 @@ def add_tools(mcp: FastMCP, client: CodeOcean):
47
41
  )
48
42
  def attach_data_assets(
49
43
  capsule_id: str,
50
- data_asset_ids: list[DataAssetAttachParamsModel],
51
- ) -> list[DataAssetAttachResultsModel]:
44
+ attach_params: list[DataAssetAttachParamsModel],
45
+ ) -> list[DataAssetAttachResults]:
52
46
  """Attach data assets to a capsule."""
53
- return [
54
- dataclass_to_pydantic(result)
55
- for result in client.capsules.attach_data_assets(capsule_id, data_asset_ids)
47
+ params = [
48
+ DataAssetAttachParams(**p.model_dump(exclude_none=True))
49
+ for p in attach_params
56
50
  ]
51
+ return client.capsules.attach_data_assets(capsule_id, params)
57
52
 
58
53
  @mcp.tool(
59
54
  description=(
@@ -62,14 +57,11 @@ def add_tools(mcp: FastMCP, client: CodeOcean):
62
57
  "Do not use for searching."
63
58
  )
64
59
  )
65
- def get_capsule(capsule_id: str) -> CapsuleModel:
60
+ def get_capsule(capsule_id: str) -> Capsule:
66
61
  """Retrieve a capsule by its ID."""
67
- return dataclass_to_pydantic(client.capsules.get_capsule(capsule_id))
62
+ return client.capsules.get_capsule(capsule_id)
68
63
 
69
64
  @mcp.tool(description=client.capsules.list_computations.__doc__)
70
- def list_computations(capsule_id: str) -> list[ComputationModel]:
65
+ def list_computations(capsule_id: str) -> list[Computation]:
71
66
  """List all computations for a capsule."""
72
- return [
73
- dataclass_to_pydantic(computation)
74
- for computation in client.capsules.list_computations(capsule_id)
75
- ]
67
+ return client.capsules.list_computations(capsule_id)
@@ -10,9 +10,6 @@ from mcp.server.fastmcp import FastMCP
10
10
  from codeocean_mcp_server.file_utils import download_and_read_file
11
11
  from codeocean_mcp_server.models import dataclass_to_pydantic
12
12
 
13
- ComputationModel = dataclass_to_pydantic(Computation)
14
- DownloadFileURLModel = dataclass_to_pydantic(DownloadFileURL)
15
- FolderModel = dataclass_to_pydantic(Folder)
16
13
  RunParamsModel = dataclass_to_pydantic(RunParams)
17
14
 
18
15
 
@@ -20,12 +17,9 @@ def add_tools(mcp: FastMCP, client: CodeOcean):
20
17
  """Add capsule tools to the MCP server."""
21
18
 
22
19
  @mcp.tool(description=client.computations.get_computation.__doc__)
23
- def get_computation(computation_id: str) -> list[ComputationModel]:
20
+ def get_computation(computation_id: str) -> Computation:
24
21
  """Retrieve a specific computation by its unique identifier."""
25
- return [
26
- dataclass_to_pydantic(computation)
27
- for computation in client.computations.get_computation(computation_id)
28
- ]
22
+ return client.computations.get_computation(computation_id)
29
23
 
30
24
  @mcp.tool(
31
25
  description=(
@@ -36,16 +30,17 @@ def add_tools(mcp: FastMCP, client: CodeOcean):
36
30
  "to retrieve outputs."
37
31
  )
38
32
  )
39
- def run_capsule(run_params: RunParamsModel) -> ComputationModel:
33
+ def run_capsule(run_params: RunParamsModel) -> Computation:
40
34
  """Execute a capsule or a pipeline in Code Ocean and don't wait."""
41
- return dataclass_to_pydantic(client.computations.run_capsule(run_params))
35
+ params = RunParams(**run_params.model_dump(exclude_none=True))
36
+ return client.computations.run_capsule(params)
42
37
 
43
38
  @mcp.tool(description=client.computations.wait_until_completed.__doc__)
44
- def wait_until_completed(computation_id: str) -> ComputationModel:
39
+ def wait_until_completed(computation_id: str) -> Computation:
45
40
  """Wait until a computation completes and return its details."""
46
- # first get the computation based on the computation_id:
47
41
  computation = client.computations.get_computation(computation_id)
48
- return dataclass_to_pydantic(client.computations.wait_until_completed(computation))
42
+ return client.computations.wait_until_completed(computation)
43
+
49
44
 
50
45
  @mcp.tool(
51
46
  description=(
@@ -53,18 +48,15 @@ def add_tools(mcp: FastMCP, client: CodeOcean):
53
48
  + " computation_id is required as string"
54
49
  )
55
50
  )
56
- def list_computation_results(computation_id: str) -> FolderModel:
51
+ def list_computation_results(computation_id: str) -> Folder:
57
52
  """List the output files generated by a completed computation."""
58
- return dataclass_to_pydantic(
59
- client.computations.list_computation_results(computation_id)
60
- )
53
+ return client.computations.list_computation_results(computation_id)
54
+
61
55
 
62
56
  @mcp.tool(description=(client.computations.get_result_file_download_url.__doc__))
63
- def get_result_file_download_url(computation_id: str, file_path: str) -> DownloadFileURLModel:
57
+ def get_result_file_download_url(computation_id: str, file_path: str) -> DownloadFileURL:
64
58
  """Get download URL for a specific result file from computation."""
65
- return dataclass_to_pydantic(
66
- client.computations.get_result_file_download_url(computation_id, file_path),
67
- )
59
+ return client.computations.get_result_file_download_url(computation_id, file_path)
68
60
 
69
61
  @mcp.tool(
70
62
  description=(
@@ -3,7 +3,6 @@ import os
3
3
  from codeocean import CodeOcean
4
4
  from codeocean.data_asset import (
5
5
  DataAsset,
6
- DataAssetAttachParams,
7
6
  DataAssetParams,
8
7
  DataAssetSearchParams,
9
8
  DataAssetSearchResults,
@@ -16,14 +15,10 @@ from mcp.server.fastmcp import FastMCP
16
15
  from codeocean_mcp_server.file_utils import download_and_read_file
17
16
  from codeocean_mcp_server.models import dataclass_to_pydantic
18
17
 
19
- DataAssetAttachParamsModel = dataclass_to_pydantic(DataAssetAttachParams)
20
18
  DataAssetModel = dataclass_to_pydantic(DataAsset)
21
19
  DataAssetParamsModel = dataclass_to_pydantic(DataAssetParams)
22
20
  DataAssetSearchParamsModel = dataclass_to_pydantic(DataAssetSearchParams)
23
- DataAssetSearchResultsModel = dataclass_to_pydantic(DataAssetSearchResults)
24
21
  DataAssetUpdateParamsModel = dataclass_to_pydantic(DataAssetUpdateParams)
25
- DownloadFileURLModel = dataclass_to_pydantic(DownloadFileURL)
26
- FolderModel = dataclass_to_pydantic(Folder)
27
22
 
28
23
 
29
24
  def add_tools(mcp: FastMCP, client: CodeOcean):
@@ -37,10 +32,10 @@ def add_tools(mcp: FastMCP, client: CodeOcean):
37
32
  "SDK."
38
33
  )
39
34
  )
40
- def search_data_assets(search_params: DataAssetSearchParamsModel) -> DataAssetSearchResultsModel:
35
+ def search_data_assets(search_params: DataAssetSearchParamsModel) -> DataAssetSearchResults:
41
36
  """Retrieve data assets matching search criteria for datasets."""
42
37
  params = DataAssetSearchParams(**search_params.model_dump(exclude_none=True))
43
- return dataclass_to_pydantic(client.data_assets.search_data_assets(params))
38
+ return client.data_assets.search_data_assets(params)
44
39
 
45
40
  @mcp.tool(
46
41
  description=(
@@ -51,14 +46,9 @@ def add_tools(mcp: FastMCP, client: CodeOcean):
51
46
  "download URL."
52
47
  )
53
48
  )
54
- def get_data_asset_file_download_url(
55
- data_asset_id: str,
56
- file_path: str | None = None,
57
- ) -> DownloadFileURLModel:
49
+ def get_data_asset_file_download_url(data_asset_id: str, file_path: str) -> DownloadFileURL:
58
50
  """Get a download URL for a specific file in a data asset."""
59
- return dataclass_to_pydantic(
60
- client.data_assets.get_data_asset_file_download_url(data_asset_id, file_path),
61
- )
51
+ return client.data_assets.get_data_asset_file_download_url(data_asset_id, file_path)
62
52
 
63
53
  @mcp.tool(
64
54
  description=(
@@ -71,22 +61,18 @@ def add_tools(mcp: FastMCP, client: CodeOcean):
71
61
  return download_and_read_file(file_url.url)
72
62
 
73
63
  @mcp.tool(description=client.data_assets.list_data_asset_files.__doc__)
74
- def list_data_asset_files(data_asset_id: str) -> FolderModel:
64
+ def list_data_asset_files(data_asset_id: str) -> Folder:
75
65
  """List files in a data asset."""
76
- return dataclass_to_pydantic(
77
- client.data_assets.list_data_asset_files(data_asset_id),
78
- )
66
+ return client.data_assets.list_data_asset_files(data_asset_id)
79
67
 
80
68
  @mcp.tool(description=client.data_assets.update_metadata.__doc__)
81
69
  def update_metadata(
82
70
  data_asset_id: str,
83
71
  update_params: DataAssetUpdateParamsModel,
84
- ) -> DataAssetModel:
72
+ ) -> DataAsset:
85
73
  """Update metadata for a specific data asset."""
86
- update_params = DataAssetUpdateParams(**update_params)
87
- return dataclass_to_pydantic(
88
- client.data_assets.update_metadata(data_asset_id, update_params)
89
- )
74
+ params = DataAssetUpdateParams(**update_params.model_dump(exclude_none=True))
75
+ return client.data_assets.update_metadata(data_asset_id, params)
90
76
 
91
77
  @mcp.tool(
92
78
  description=(
@@ -100,16 +86,14 @@ def add_tools(mcp: FastMCP, client: CodeOcean):
100
86
  data_asset: DataAssetModel,
101
87
  polling_interval: float = 5,
102
88
  timeout: float | None = None,
103
- ) -> DataAssetModel:
89
+ ) -> DataAsset:
104
90
  """Wait until a data asset is ready."""
105
- result = client.data_assets.wait_until_ready(
91
+ return client.data_assets.wait_until_ready(
106
92
  DataAsset(**data_asset.model_dump(exclude_none=True)),
107
- polling_interval=polling_interval,
108
- timeout=timeout,
93
+ polling_interval,
94
+ timeout,
109
95
  )
110
96
 
111
- return dataclass_to_pydantic(result)
112
-
113
97
  @mcp.tool(
114
98
  description=(
115
99
  str(client.data_assets.create_data_asset.__doc__)
@@ -117,7 +101,7 @@ def add_tools(mcp: FastMCP, client: CodeOcean):
117
101
  f"with the pattern: {os.getenv('CODEOCEAN_DOMAIN', 'unknown')} with /data-assets/<data_asset_id>."
118
102
  )
119
103
  )
120
- def create_data_asset(data_asset_params: DataAssetParamsModel) -> DataAssetModel:
104
+ def create_data_asset(data_asset_params: DataAssetParamsModel) -> DataAsset:
121
105
  """Create a new data asset."""
122
106
  params = DataAssetParams(**data_asset_params.model_dump(exclude_none=True))
123
- return dataclass_to_pydantic(client.data_assets.create_data_asset(params))
107
+ return client.data_assets.create_data_asset(params)
@@ -46,7 +46,7 @@ def test_prompt_generates_correct_tool_usage_sequence(
46
46
  if not prompt:
47
47
  prompt = agentic_prompt_chain["prompt"]
48
48
  else:
49
- prompt += str(responses) + "\nwhat is the next steps?\n"
49
+ prompt += str(responses) + "\nwhat is the next step?\n"
50
50
  response = call_bedrock(prompt=prompt, tools=tools)
51
51
  check_diff(step[0], response)
52
52
  responses.append(
@@ -399,7 +399,7 @@ test_response = [
399
399
  },
400
400
  },
401
401
  # --------------------------------------------------------------
402
- # update metada: custome metadata
402
+ # update metadata: custom metadata
403
403
  {
404
404
  "id": "update_metadata_custom_metadata",
405
405
  "prompt": "update metadata for data asset with id: data_asset102, set custom metadata 'key1' to 'value1' and 'key2' to 'value2'", # noqa: E501
@@ -350,7 +350,7 @@ wheels = [
350
350
 
351
351
  [[package]]
352
352
  name = "codeocean"
353
- version = "0.7.0"
353
+ version = "0.8.0"
354
354
  source = { registry = "https://pypi.org/simple" }
355
355
  dependencies = [
356
356
  { name = "backports-strenum", marker = "python_full_version < '3.11'" },
@@ -358,14 +358,14 @@ dependencies = [
358
358
  { name = "requests" },
359
359
  { name = "requests-toolbelt" },
360
360
  ]
361
- sdist = { url = "https://files.pythonhosted.org/packages/be/80/d6d7adb680439c612fb4bcf82744dd4d8f62b92b2cef91922de9132140a2/codeocean-0.7.0.tar.gz", hash = "sha256:1797c37d1ba4d60eb4215455eca4d094d6e4564010eafca75601479e0353030d", size = 14477, upload-time = "2025-06-24T21:55:46.971Z" }
361
+ sdist = { url = "https://files.pythonhosted.org/packages/e6/66/c947525bd7bdbc8dd337b3ab0badd4be9c47a4869404640c6e000e3ec5a8/codeocean-0.8.0.tar.gz", hash = "sha256:fbbff4de028f034495584731ca3a4830d9a90a97b88839cfe16aeaebb5caa561", size = 15530, upload-time = "2025-07-11T16:50:17.372Z" }
362
362
  wheels = [
363
- { url = "https://files.pythonhosted.org/packages/4f/51/f1eb42ec8eccea8febb82e2346833204ee0dd2959daeee72123c284dc8b3/codeocean-0.7.0-py3-none-any.whl", hash = "sha256:b0fd9869db25399cc01388cf1fdaaeebeaf7faa53463496354e38f561f0050aa", size = 15959, upload-time = "2025-06-24T21:55:47.663Z" },
363
+ { url = "https://files.pythonhosted.org/packages/9e/16/d8a220ef5ea2f938be973394f23687208dcfb3ba737c022e88f3d6a97134/codeocean-0.8.0-py3-none-any.whl", hash = "sha256:73feba7c9c2c03a21ba07feaf0e946e3087d2d29af38efbd61d452dd7a8ef1a5", size = 16365, upload-time = "2025-07-11T16:50:18.622Z" },
364
364
  ]
365
365
 
366
366
  [[package]]
367
367
  name = "codeocean-mcp-server"
368
- version = "0.1.0"
368
+ version = "0.3.0"
369
369
  source = { editable = "." }
370
370
  dependencies = [
371
371
  { name = "codeocean" },
@@ -384,7 +384,7 @@ dev = [
384
384
 
385
385
  [package.metadata]
386
386
  requires-dist = [
387
- { name = "codeocean", specifier = ">=0.7.0" },
387
+ { name = "codeocean", specifier = ">=0.8.0,<0.9.0" },
388
388
  { name = "fastmcp", specifier = ">=2.9.2" },
389
389
  ]
390
390
 
@@ -1,6 +0,0 @@
1
- CHANGELOG
2
- =========
3
-
4
- ## 0.1.0 (2025-07-01)
5
-
6
- - [#1](https://github.com/codeocean/codeocean-mcp-server/pull/1) Initial version