Skip to content

Releases: sassoftware/sas-mcp-server

v1.5.0 — SAS Intelligent Decisioning tools & opt-in usage telemetry

Choose a tag to compare

@Criptic Criptic released this 07 Jul 11:46
v1.5.0
bfcb79e

Highlights

🧩 SAS Intelligent Decisioning — 23 new tools (#25)

Author and operate SAS Intelligent Decisioning rule sets and decision flows end to end, directly from the MCP server:

  • Rule sets & rules — create / update / get / list / delete rule sets and the conditional rules inside them, plus lock and list immutable rule-set revisions.
  • Decision flows — create / update / get / list / delete flows that chain rule-set steps, retrieve their generated DS2 code, and lock / list / fetch decision revisions.
  • Publish & scorepublish_decision_flow publishes a locked revision to Micro Analytic Score (MAS), polls the asynchronous Model Publish job to completion, and returns the server-generated MAS moduleId — so the result is immediately usable with the new get_mas_module_step_signature and the existing score_data, with no separate lookup.

📊 Opt-in "collection mode" usage telemetry (#24)

An off-by-default mode that helps maintainers learn how the server is actually used — which tools, for what goals, with what inputs, and where they fall short. Implemented as a FastMCP middleware that requires no changes to any tool:

  • Injects a per-call goal the model fills in (stripped before the tool runs), and appends one redacted, size-bounded JSON Lines record per call to a rotating local log.
  • Nothing is ever transmitted anywhere — the log stays on the machine running the server, and sharing it with maintainers is a deliberate, manual step. Secret-shaped keys and inline Bearer/JWT tokens are redacted, results default to a content-free shape summary, and the log file is locked to the current user.
  • Enable with COLLECTION_MODE=true; see the Collection Mode section of the README for the full COLLECTION_* configuration.

🔢 Tool count

The server now exposes 68 tools spanning code execution, data discovery, data operations & files, reports, batch jobs, model management & scoring, decisioning, compute contexts, and the SAS Information Catalog.

🐳 Container image

Published to GHCR on release:

ghcr.io/sassoftware/sas-mcp-server:1.5.0   # also tagged 1.5 and latest

📄 Details

Unified Report Export & AutoML Champion Model Publishing

Choose a tag to compare

@Criptic Criptic released this 02 Jul 15:03

Added

  • AutoML champion model register/publish tools (3) (#22) — register_ml_champion_model registers an AutoML pipeline automation project's champion model to the Model Repository; publish_ml_champion_model publishes it to a scoring destination; list_publishing_destinations lists the available destinations to publish to. All three drive the mlPipelineAutomation champion-model action endpoint (register/publish), shared via helpers/auto_ml_helpers.py. Brings the tool count to 45.
  • export_report tool (#18) — one tool covering every synchronous Visual Analytics report export: package (zip), pdf, png, svg, csv, tsv, xlsx, and summary, for a whole report or selected report objects. Results are returned with native MCP content types — text inline for text formats, image content for png, and an embedded binary file (carrying the correct MIME type, e.g. application/zip for packages) for package/pdf/xlsx — instead of a hand-rolled base64 JSON blob. Per-format input validation enforces the API's object-count and image_size rules; binary exports larger than MAX_EXPORT_INLINE_BYTES (default 25 MiB) are refused with guidance rather than streamed through the model context; and a Viya HTTP error is surfaced as a structured export_failed result instead of a raised exception. The format registry, validation, and request execution live in helpers/report_export_helpers.py so the tool stays a thin wrapper.

Changed — BREAKING

  • export_report_package has been replaced by export_report. The old tool hit the wrong route (/visualAnalytics/getExportedReportPackage/{id}/package, the operationId rather than the path) and sent reportObjects as a JSON body on a GET. Use export_report with export_format="package"; report objects are passed via report_objects.

Removed — BREAKING

  • get_report_image has been removed, superseded by export_report. It used the reportImages service to return an async job descriptor (not the image itself) for a report section thumbnail. export_report with export_format="png" or "svg" renders the whole report or a single object and returns the actual image bytes as native MCP content.

SAS Information Catalog Tools & Reference-Based Uploads

Choose a tag to compare

@Criptic Criptic released this 24 Jun 07:59
359c01a

Added

  • SAS Information Catalog tools (9) (#19) — catalog_search, catalog_search_helper, catalog_find_instance, catalog_list_agents, catalog_run_agent, catalog_get_agent_history, catalog_run_adhoc_analysis, catalog_get_adhoc_analysis, and catalog_download_table_profile. Metadata discovery and profiling across the whole Viya environment: search assets with the catalog grammar (free text + facets), resolve a search hit's catalog instance, submit and poll ad-hoc profiling jobs (with NLP enrichment for privacy/semantic tags), download a table's data dictionary + column profile as CSV, and list/run/inspect the discovery agents that populate the catalog. Brings the tool count to 41.
  • upload_inline_data tool — creates a small CAS table from inline csv/tsv text passed as a string (a lookup/mapping table the model builds on the fly, or a quick test table). This is the deliberate "data travels through the model context" path, split out from upload_data so the cost is explicit in the tool you pick. Brings the tool count to 42.

Changed — BREAKING

  • upload_data is now reference-only and no longer takes csv_data. It accepts the data by reference through exactly one of file_path (the server reads it off its own disk) or url (the server fetches it), so the payload is read server-side and never passes through the calling model's context. Inline text moved to the new upload_inline_data tool. file_path reads from the host the server runs on (in stdio mode, the user's machine) and can be disabled by operators with ALLOW_LOCAL_FILE_UPLOAD=false. Callers that passed csv_data should switch to upload_inline_data (for genuinely small tables) or write the data to a file/URL and use upload_data.

Changed

  • upload_data accepts more formats. Beyond CSV it ingests every format the casManagement uploadTable API accepts — tsv (csv + tab delimiter), xls, xlsx (single sheet), sas7bdat, and sashdat. The format is auto-detected from the file_path/url extension and can be overridden with data_format; sheet_name (Excel) and contains_header_row arguments tune the import. parquet is not accepted by that endpoint (confirmed against the API spec and a live HTTP 400) and is rejected up front with guidance to load it via a path-based caslib + promote_table_to_memory or convert it first.
  • catalog_search and catalog_search_helper use the shared return_items field projection for their result shaping (#19).

Fixed

  • stdio token resolution is now expiry-aware (#20). The resolver returned the first cached access token it found without checking expiry, so an expired SAS Viya CLI cache (~/.sas) could shadow a valid helper cache (~/.sas-mcp-server) and make every Viya call fail with 401. A token at or past its expiry (minus a 60s skew) is now skipped so resolution falls through to the next source; when a cache's access token is expired but it still holds a refresh token, it is exchanged for a fresh one using the client that minted it (sas.cli for the CLI cache, vscode for the helper cache), written back to that cache, and used. Refresh is best-effort — a wrong client, revoked token, or network error falls through cleanly to the next source or the device-code flow — and a missing/unparseable expiry is treated as not-expired, preserving prior behaviour.

Compute Data and Reusable SAS Session

Choose a tag to compare

@Criptic Criptic released this 16 Jun 09:57
9635389

Added

  • Compute service discovery toolslist_compute_contexts, list_compute_libraries, list_compute_tables, list_compute_columns — browse compute contexts and the SAS libraries/tables/columns visible inside a compute session. Brings the tool count to 32.
  • reset_compute_session tool — deletes the cached compute session for the caller and compute context, discarding its SAS state (WORK tables, macro variables, assigned librefs) so the next call starts from a fresh session. Defaults to the configured execution context.
  • Reusable, per-user compute session cache (_ComputeSessionCache in viya_utils.py) — one warm compute session is kept per authenticated user and compute context, so repeat calls skip the slow session spin-up. Keyed by the JWT sub claim (falling back to other identity claims, then a token hash) so multi-user HTTP deployments never share a session. Cached sessions are validated before reuse and transparently recreated if Viya has reaped them for inactivity.
  • Compute session shutdown cleanup — both server entry points register a FastMCP lifespan that deletes all cached compute sessions on shutdown (best effort), so warm sessions don't linger until Viya's idle reaper collects them.
  • Integration coverage for every new tooltest_compute_discovery_workflow and test_compute_session_reuse_and_reset (which proves reuse, deletion, and recreation end to end against a live Viya), wired into the test_every_tool_has_integration_coverage guard.
  • return_items helper (viya_client.py) — shared field-projection used by the compute discovery tools.

Changed — BREAKING

  • execute_sas_code is now stateful across calls. It runs in the reusable per-user compute session, so SAS WORK tables, macro variables, and assigned librefs persist between successive calls instead of being discarded with a per-call session. Call reset_compute_session to start from a clean session. (Previously every call created and tore down its own session.)

Changed

  • get_context_id and create_session now call raise_for_status(), so an auth/permission failure surfaces as a real HTTPStatusError instead of a misleading "compute context not found" or a KeyError.
  • get_context_id builds its query with httpx params= instead of string interpolation, so compute context names containing reserved characters (&, +, #) are encoded correctly.
  • The compute session lifecycle (resolve context → create → reuse/reset/teardown) is centralised in _ComputeSessionCache; run_one_snippet and the compute tools now share it, and delete_session was extracted as a reusable helper.