Skip to content

Apiv2 cmlapi methods#16

Merged
Khauneesh-AI merged 6 commits into
devfrom
apiv2-cmlapi-methods
May 12, 2026
Merged

Apiv2 cmlapi methods#16
Khauneesh-AI merged 6 commits into
devfrom
apiv2-cmlapi-methods

Conversation

@Khauneesh-AI
Copy link
Copy Markdown
Collaborator

Summary

  • Migrated all 98 tool functions from hand-rolled requests calls to the official cmlapi Python SDK using CMLServiceApi
  • Added shared setup_client() and serialize_result() helpers in http_helpers.py
  • Net change: -7,320 lines, +2,245 lines across 103 files

Why

The previous implementation manually constructed URLs, headers, payloads, and error handling in every function. Most tool functions had roughly 80–130 lines of repeated request-handling logic.

This caused several issues:

  • Silent failures, for example delete_application returning success without actually deleting the application
  • Wrong URL patterns, such as /stop vs :stop and /restart vs :restart
  • Missing fields in update payloads
  • Inconsistent error handling across tools
  • High maintenance overhead when adding or fixing API operations

Moving to the official SDK makes the implementation smaller, more consistent, and less prone to endpoint or payload drift.


What changed

  • All tool functions now use the common SDK flow:

    client = setup_client(host, api_key)
    result = client.method_name(...)
    return serialize_result(result)
  • Added shared SDK helpers in http_helpers.py:

    • setup_client(host, api_key)
    • serialize_result(result)
  • create_registered_model now uses typed SDK objects:

    • CreateRegisteredModelRequest
    • Tag

    Raw dictionaries do not serialize correctly for this endpoint.

  • upload_file remains requests-based because multipart PUT upload is not supported by the SDK.

  • stdio_server.py fixes:

    • Fixed 4 tool wrappers that were returning raw dictionaries instead of json.dumps(...)
  • Tests updated to mock cmlapi instead of requests.

  • README updated with:

    • Architecture section
    • Updated prerequisites
    • Troubleshooting guidance

Test plan

  • All unit tests pass:

  • Syntax check completed on all 107 function files.

  • MCP live testing against Workbench completed for tools, including:

    • Applications CRUD
    • Jobs CRUD
    • Experiments
    • Models
    • Registered models
    • Runtimes
    • Project files
    • Collaborators
    • Admin/quota endpoints

Known limitations

  • list_experiment_runs does not support the sort parameter. The API returns 400, which appears to be an upstream limitation.
  • create_experiment_run via API creates metadata only. Model artifacts still require MLflow running inside a CML session or job.
  • Some admin endpoints, such as quotas and accelerator labels, return 403 for non-admin users. This is expected behavior.

Khauneesh-AI and others added 6 commits May 12, 2026 19:23
  Migrate 6 high-priority functions (delete/stop/restart/update/create_application,
  get_runtimes) from hand-rolled requests to cmlapi.CMLServiceApi. Add shared
  setup_client() to http_helpers.py. Fixes silent failures on delete, wrong URL
  patterns for stop/restart, and incorrect field names in get_runtimes.

  - Reduces ~676 lines of boilerplate to ~246 lines of typed SDK calls
  - Errors now properly surfaced via ApiException instead of silent success
  - upload_folder.py updated to reuse shared setup_client
  - Test assertions updated to accept cmlapi as valid HTTP transport
…m cmlapi

cmlapi SDK returns datetime objects in responses which break JSON
serialization in the MCP transport layer. Add serialize_result() to
http_helpers that round-trips through json.dumps(default=str).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace hand-rolled requests calls with cmlapi.CMLServiceApi methods
across all function files. Adds setup_client() and serialize_result()
to http_helpers.py as shared infrastructure.

Key changes:
- All tools now use typed SDK calls instead of manual URL construction
- serialize_result() handles datetime serialization from SDK responses
- create_registered_model uses CreateRegisteredModelRequest + Tag objects
- list_project_files passes path as required positional arg
- stdio_server.py: fix 4 tools returning dicts instead of JSON strings
- Tests updated to mock cmlapi instead of requests
- README updated with architecture note and cmlapi prerequisite
- .gitignore: add .mcp.json (contains local credentials)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace TOOL_IMPLEMENTATIONS lambda dict with proper @mcp.tool()
decorated functions so all tools appear in FastMCP tools/list.
Previously only 58 of 104 tools were discoverable.

Also fixes:
- create_registered_model: handle both dict and plain string tags
- test assertions updated for CreateRegisteredModelRequest object
- list_project_files test: path is positional arg

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Move cmlapi imports behind try/except (ApiException falls back to
Exception) and inside function bodies (setup_client, create_registered_model).
This allows the package to import and tests to collect without cmlapi
installed — required for GitHub Actions CI where cmlapi is unavailable.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When cmlapi is unavailable, ApiException = Exception was too broad —
it caught ModuleNotFoundError from setup_client() and then crashed
accessing e.status. Fix: define a placeholder ApiException class that
only matches itself, so real errors fall through to except Exception.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@Khauneesh-AI Khauneesh-AI merged commit 8140710 into dev May 12, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant