Skip to main content
Glama

sas-mcp

An MCP server that lets coding agents — Claude Code, Claude Desktop, GitHub Copilot, Cursor — write, run, and validate SAS 9.4 code through SASPy.

It runs locally as a stdio subprocess on your own machine. Nothing is hosted, and your code and data never leave your environment: SASPy connects to whatever SAS you already have.

Why not just let the agent call sas.submit()?

Wrapping submit() is thirty lines. The reason this package exists is the three layers around it:

  • Log triage. SAS logs are enormous and the signal is buried. Worse, SAS routinely succeeds while being semantically wrong. A misspelled variable, a many-to-many merge, a silent character-to-numeric conversion — all of these return zero errors and a wrong answer. run_sas returns status: "suspicious" for exactly that class, so an agent can't mistake it for success.

  • Schema discovery. Hallucinated column names are the most common way an LLM writes broken SAS. describe_dataset removes the guessing.

  • Guardrails. An agent improvising proc datasets lib=prod kill; against a production libref is a career event. Writes are restricted to WORK by default.

Related MCP server: python-executor-mcp

Install

pip install sas-mcp     # or: uv tool install sas-mcp

First run: create your SAS configuration

SASPy needs a sascfg_personal.py describing where your SAS lives. If you already run SASPy you have one and can skip ahead — this uses it as-is.

If you don't, don't hand-write it. Run:

sas-mcp init

It asks where your SAS runs, finds a working Java runtime for you, and writes a correct config to the right place:

Where does your SAS run?
  1. SAS OnDemand for Academics (free, cloud)
  2. SAS installed locally on this Linux/UNIX machine
  3. SAS installed locally on this Windows machine
  4. SAS server on my network (IOM / Workspace Server)
  5. SAS on a remote UNIX host over SSH
Choice [1-5]: 1

Which ODA home region? (shown at welcome.oda.sas.com)
  1. United States (Home Region 1)
  ...
  Found a working Java runtime: /Library/Java/.../bin/java

Wrote /Users/you/.config/saspy/sascfg_personal.py
Save your SAS credentials to /Users/you/.authinfo now? [Y/n]:

For ODA and intranet IOM servers it also offers to write your credentials to ~/.authinfo (_authinfo on Windows). The password is prompted without echo and the file is created owner-only — SASPy needs it in the clear, so permissions are the only thing protecting it, and init sets them rather than trusting you to remember.

Then verify:

sas-mcp doctor   # is the configuration sane? (never connects)
sas-mcp check    # does it actually work? (starts a real SAS session)

doctor is deliberately offline, so it still works when the connection is exactly what's broken. check runs those same checks and then connects:

[PASS] connect: Connected (SAS 9.04.01M8P02222023, encoding utf-8)
[PASS] submit: DATA step ran; WORK._SASMCP_PROBE = 19 rows.
[PASS] log_notes: Log triage is working: flagged suspicious
       (missing_values_generated, uninitialized_variable).
[PASS] schema: Schema discovery works (5 columns, 19 rows).
[PASS] encoding: Non-ASCII round-trip is clean ('café').

The log_notes probe is the important one. It submits code with a misspelled variable — code that must be flagged — and fails if it isn't. A session with NONOTES set runs everything successfully while the triage layer sees nothing, so results look like clean successes while being wrong. A passing submit does not prove triage works; only this does.

The encoding probe round-trips a non-ASCII string, since an encoding mismatch corrupts character data silently rather than raising.

check uses a real SAS session, which counts against concurrency limits on ODA and licensed servers, and it cleans up the WORK tables it creates. sas-mcp doctor --connect is the same thing.

It can also run unattended, for scripted or team setup:

sas-mcp init --deployment oda --region us1

Regions are us1, us2, eu1, ap1, ap2; your home region is shown at welcome.oda.sas.com. init never overwrites an existing config or credential entry without --force.

Where the config goes

init writes to your home directory, which works the same on every platform:

Platform

Location

macOS / Linux

~/.config/saspy/sascfg_personal.py

Windows

%USERPROFILE%\.config\saspy\sascfg_personal.py

SASPy calls expanduser("~/.config/saspy/") on all platforms, so Windows uses that same .config folder under your user directory — not AppData.

Be aware that this is the lowest-priority location SASPy searches:

  1. An explicit cfgfile path (what --config-file passes)

  2. The saspy package directory inside site-packages

  3. The working directory (sys.path[0])

  4. ~/.config/saspy/

So a sascfg_personal.py left in site-packages or in your project folder will silently win over your home copy. Two consequences worth knowing:

  • A config inside site-packages is deleted when you rebuild your virtualenv or reinstall saspy. Keep it in your home directory instead.

  • There is no environment variable for this. SASPy reads none when resolving a config, so --config-file is the only unambiguous way to pin it:

    sas-mcp serve --config-file ~/.config/saspy/sascfg_personal.py --config oda

sas-mcp doctor reports which file actually wins, warns when several exist, and flags a config living somewhere a reinstall will destroy.

Check your setup first

sas-mcp doctor

This is the fastest way past the usual configuration problems, and it runs without connecting to SAS — so it still works when the connection is what's broken. It checks the config file and access method, the Java runtime that IOM requires, ~/.authinfo presence and permissions, ODA hostname validity, network reachability, and encoding. Every failure comes with the fix.

[FAIL] java: /usr/bin/java exists but no Java runtime is installed.
         fix: On macOS /usr/bin/java is only a stub. Install a real JRE, e.g.
              `brew install --cask temurin`, then set 'java' to the full path
              from `/usr/libexec/java_home`.
[FAIL] authinfo_permissions: ~/.authinfo is readable by group or others
       (mode 0o644). SASPy refuses to use it and your SAS password is exposed
       to other local accounts.
         fix: chmod 600 ~/.authinfo

When anything fails, the report also links SASPy's troubleshooting guide, which covers the IOM, Java, and encryption problems this tool can detect but not fix for you.

If your password "doesn't work"

SASPy parses ~/.authinfo by requiring a line to split into exactly five whitespace-separated fields:

<key> user <username> password <password>

A password containing a space produces six fields, so SASPy skips the line entirely and reports "did not find key" — which sends you looking for a missing entry rather than a mis-parsed one. Trailing comments break it the same way.

Two fixes:

  • Use a password with no spaces, or

  • Store a SAS PWENCODE value instead — {SAS004}... is always a single token, so it sidesteps the problem. These authenticate fine against both ODA and intranet IOM servers. Note it's obfuscation, not encryption: the file still needs chmod 600.

sas-mcp doctor checks the field count directly and names this cause.

On Windows, also check the file's encoding. SASPy opens _authinfo with open(pwf, mode='r') — the locale default, typically cp1252, not UTF-8. If your editor saved it as UTF-8 and the password contains a non-ASCII character, the bytes decode into something longer: à becomes à + \xa0, and \xa0 (NBSP) counts as whitespace to split(), so the line gains a field and is skipped. Save the file as ANSI/cp1252, or use an ASCII-only password.

SAS encryption jars (needed for ODA)

SASPy does not ship the SAS encryption jarssas.rutil.jar, sas.rutil.nls.jar, and sastpj.rutil.jar are absent from a clean install, though SASPy puts them on the IOM classpath regardless. They are a manual download.

Whether you need them depends on the server:

  • SAS ODA always requires an encrypted connection. Without these jars it fails even when everything else is correct — as a Java error that never mentions a missing file. sas-mcp doctor reports this as a failure.

  • An intranet IOM server may not require encryption, so doctor reports it as information rather than treating a fresh install as broken.

Either way, doctor names the missing files, links the SAS download, and prints the exact destination. They must go in SASPy's own saspy/java/iomclient/ directory — that path is hardcoded where SASPy builds the IOM classpath, so no other location will be found. Doctor prints the resolved absolute path for your install.

Connect your agent

Claude Code

claude mcp add sas -- sas-mcp serve

Claude Desktop — in claude_desktop_config.json:

{
  "mcpServers": {
    "sas": { "command": "sas-mcp", "args": ["serve"] }
  }
}

VS Code / GitHub Copilot — in .vscode/mcp.json:

{
  "servers": {
    "sas": { "type": "stdio", "command": "sas-mcp", "args": ["serve"] }
  }
}

Add policy flags to args as needed, e.g. ["serve", "--config", "oda", "--writable-libs", "STAGE"].

Choosing between multiple SAS environments

If your sascfg_personal.py defines more than one configuration, decide who picks:

Pin it in the client config — the agent uses this one and cannot switch:

{
  "servers": {
    "sas": { "command": "sas-mcp", "args": ["serve", "--config", "oda"] }
  }
}

Add --allow-config-switch to make it a starting point the agent may change instead of a restriction.

Or leave --config off, and the agent chooses: list_sas_configs shows what's available with each one's access method and target server, and use_sas_config selects one. With exactly one configuration defined it's used automatically and nothing is asked.

Either way the server never blocks waiting for an answer. Left to itself, SASPy prompts on stdin for a configuration name — and on a stdio MCP server stdin is the JSON-RPC stream, so the prompt would consume protocol bytes and hang the client. sas-mcp disables SASPy's prompting entirely and returns the choice as data instead.

Tools

Tool

Purpose

sas_doctor

Diagnose configuration without connecting

session_status

Connection, SAS version, librefs, WORK contents, policy

run_sas

Submit code; returns triaged status, findings, row counts, output

get_last_log

Full raw log, when triage isn't enough

reset_session

Clear WORK

list_libraries

Assigned librefs with paths and writability

list_datasets

Tables in a library with row/column counts

describe_dataset

Columns with type, length, format, label

sample_rows

First N rows as records

compare_datasets

PROC COMPARE as a structured diff

run_sas_tests

Run code with assertion macros; report pass/fail

What run_sas returns

Not a log — a verdict:

{
  "status": "suspicious",
  "summary": "Ran, but results may be wrong: 2 suspicious notes; created WORK.B=19 obs.",
  "suspicious_notes": [
    {
      "rule": "uninitialized_variable",
      "text": "NOTE: Variable weigth is uninitialized.",
      "explanation": "Variable was read before being assigned, so it evaluates to missing. Almost always a misspelled variable name.",
      "line_no": 5
    }
  ],
  "steps": [{"step": "DATA statement", "dataset": "WORK.B", "obs_out": 19}],
  "output": "..."
}

status is ok, suspicious, or error. suspicious means the code ran and the answer is probably wrong — it is not a success.

Every result also carries log_file: a path to a saved file holding the findings and the complete SAS log, so "check the log" is something you can actually act on. Logs go to a temporary directory by default; --log-dir PATH puts them somewhere you choose, and the 25 most recent are kept.

Validating code

Rather than teach an agent a niche SAS test framework, this builds on the tool SAS developers already use — and which happens to be machine-readable. PROC COMPARE sets &SYSINFO to a bitmask where each bit names a specific kind of difference, so compare_datasets can distinguish "the values disagree" from "only a format differs":

{
  "identical": false,
  "data_differs": true,
  "metadata_only": false,
  "findings": [
    {"code": "base_obs", "meaning": "Base data set has observations not in comparison"},
    {"code": "value",    "meaning": "At least one value comparison was unequal"}
  ],
  "summary": "Data sets differ: ..."
}

That makes it a real assertion an agent can iterate against — the natural way to verify that a rewritten step reproduces the original result.

run_sas_tests adds a small assertion macro library, loaded into the session on first use:

%assert_exists(work.out);
%assert_rows(work.out, 19);
%assert_not_empty(work.out);
%assert_no_missing(work.out, age);
%assert_unique(work.out, id);
%assert_equal_datasets(work.expected, work.out);
%assert_condition(&n > 0, detail=n must be positive);

Each writes a marker to the log that comes back as structured pass/fail. A failed assertion sets status: "assertions_failed" even when the log itself is clean — a green log with a red assertion is not a pass.

Getting files out of SAS

SAS ODA runs in AWS and an intranet SAS server sits on another machine, so neither can see your local disk. SASPy transfers over the SAS connection itself, which works regardless:

run_sas:           proc export data=sashelp.class
                     outfile="~/report.xlsx" dbms=xlsx replace; run;
list_sas_files:    ~            -> report.xlsx
download_from_sas: ~/report.xlsx -> /tmp/sas-mcp-files-xxxx/report.xlsx

upload_to_sas goes the other way, for sending a CSV or workbook in.

Everything the server writes for you lands in your working folder, so it shows up in the editor's file tree:

sas-mcp/
  .gitignore        excludes this directory automatically
  files/            downloads land here; uploads may only read from here
  logs/             one annotated log per submission

Override with --file-dir PATH and --log-dir PATH. If the client starts the server somewhere unwritable, both fall back to a temporary directory.

Transfers are confined to that one directory, so the agent can neither overwrite arbitrary local files nor send arbitrary local files to a remote server. To upload something else, copy it in first.

Safety

Writes are restricted to WORK by default. Also blocked unless you opt in:

  • OS escapesX, %SYSEXEC, SYSTASK COMMAND, CALL SYSTEM, FILENAME PIPE, PROC PYTHON/LUA/GROOVY

  • Destructive DDLPROC DATASETS KILL/DELETE, DROP TABLE, PROC DELETE, FDELETE

  • Libref rebinding — re-pointing an allowlisted libref somewhere else

Reads are never restricted; an agent can set prod.sales freely.

sas-mcp serve --writable-libs STAGE,SCRATCH   # widen the write allowlist
sas-mcp serve --allow-destructive             # permit DROP/KILL/DELETE
sas-mcp serve --allow-os-escape               # permit X, PIPE, etc.

Scope of the guarantee

This is a defense against model error, not a security boundary. SAS can generate code at run time through CALL EXECUTE, DOSUBL, and macro expansion, so no static scan can be complete, and a determined bypass is always possible. It reliably stops the common accident. Do not rely on it as your only control on a system where an agent could do real damage — use a SAS account whose own permissions match what you want to allow.

Two known gaps, stated plainly:

  • Filesystem writes (PROC EXPORT ... OUTFILE=, ODS to a path) are not restricted, only SAS library writes.

  • Code assembled at run time from fragments that are individually innocuous will not be caught.

Supported deployments

The SAS 9.4 setups SASPy handles, selected by your sascfg_personal.py:

Deployment

Access method

Needs

Verified

SAS OnDemand for Academics

IOM

Java, ~/.authinfo

✅ macOS + Windows

Intranet SAS server

IOM

Java, ~/.authinfo

✅ Windows

Intranet SAS server

SSH

SSH keys

not yet

Local Windows install

COM

pywin32 (no Java)

not yet

Local Windows install

IOM

Java

not yet

Local Linux/UNIX install

STDIO

saspath

not yet

"Not yet" means generated and unit-tested but not exercised against a running SAS — run sas-mcp check and it will tell you whether your setup works. If one of these fails for you, that's a bug worth reporting.

SAS ODA is free but its terms are academic and non-commercial use only.

Note that each MCP client starts its own server process and therefore its own SAS session, which counts against concurrent-session limits on both ODA and licensed servers.

Development

uv pip install -e ".[dev]"
pytest

The log parser and guardrails are pure functions with no SAS dependency, and the server tests run against a fake session — so the full suite runs anywhere. CI runs them on Linux, macOS, and Windows against Python 3.10, 3.12, and 3.14.

Testing on Windows

CI runs the suite on Windows, but that cannot reach a SAS installation. To test against real Windows SAS, on the Windows machine:

# No PyPI release needed -- install straight from the repo
pip install git+https://github.com/matise-joe-norc/sas-mcp

sas-mcp init      # choose the COM option first; it needs no Java
sas-mcp doctor

Local Windows SAS has two access methods, and COM is worth trying first: it needs no Java at all, which removes the most common Windows setup failure. It does need pip install pywin32. The IOM option is the fallback if COM gives trouble.

Then exercise the server end to end:

python -c "from sas_mcp.session import SASSessionManager as M; m=M(cfgname='wincom'); r=m.submit('data work.a; set sashelp.class; run;'); print(r.triage.status, r.triage.summary)"

Expect ok Ran: created WORK.A=19 obs. A result of ok with no steps reported means the log has no NOTEs — see the options notes note below.

The two things most likely to differ from the verified Linux/ODA path:

  • Encoding. Windows SAS 9.4 typically runs wlatin1, not UTF-8. A mismatch shows up as mojibake in character columns rather than an error. sas-mcp doctor reports the configured value.

  • NONOTES. SASPy's IOM sessions suppress the NOTE: lines that log triage depends on. The session manager sets options notes source; on connect; if a Windows session somehow overrides that, run_sas would return ok with empty steps and no suspicious_notes.

To confirm triage is really working rather than silently blind, run something that should be flagged:

python -c "from sas_mcp.session import SASSessionManager as M; m=M(cfgname='wincom'); r=m.submit('data work.b; set sashelp.class; bmi=weigth/height; run;'); print(r.triage.status, [n.rule for n in r.triage.suspicious_notes])"

Expect suspicious ['uninitialized_variable', 'missing_values_generated']. If that returns ok with an empty list, triage is not seeing NOTEs and the result is untrustworthy — report it as a bug.

Releasing

The version lives in exactly one place: __version__ in src/sas_mcp/__init__.py. Packaging metadata reads it from there, so the two can't drift.

  1. Bump __version__ and add a CHANGELOG.md entry.

  2. Commit, and confirm CI is green on main.

  3. Publish a GitHub Release tagged vX.Y.Z.

That triggers release.yml, which builds, runs twine check, installs the built wheel into a clean virtualenv to confirm it actually runs, verifies the tag matches __version__, and only then publishes. The tag check matters because PyPI will not let you re-upload a filename — a mismatched tag is not recoverable.

workflow_dispatch runs the same build and verification without publishing, if you want a dry run first.

One-time PyPI setup

Publishing uses Trusted Publishing, so there is no API token to store or rotate. Before the first release, add a pending publisher at pypi.org/manage/account/publishing:

Field

Value

PyPI project name

sas-mcp

Owner

matise-joe-norc

Repository name

sas-mcp

Workflow name

release.yml

Environment name

pypi

Then create a pypi environment under the repository's Settings → Environments. Adding a required reviewer there gives you a manual approval gate before anything reaches PyPI.

License

MIT

Available Tools

16 tools
compare_datasetsA
Read-only

Run PROC COMPARE between two data sets and return a structured diff: whether they are identical, whether the difference is in the data or only in metadata (labels, formats, lengths), and the specific kinds of difference found. This is the primary way to validate that a rewrite produces the same result as the original.

ParametersJSON Schema
NameRequiredDescriptionDefault
byNo
baseYes
compareYes
criterionNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, so the safety profile is covered. The description adds behavioral detail beyond that by specifying the structured output: whether data sets are identical, whether differences are in data or metadata, and the specific kinds of differences. It does not contradict the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences with no unnecessary words. The first sentence front-loads the core function and output; the second provides the key use case. It is concise, structured, and every clause earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description covers the tool's purpose, output, and primary use case, and the output schema can define the return structure. However, given 0% schema parameter coverage, the optional `by` and `criterion` parameters are left unexplained, and there is no mention of SAS session prerequisites or behavior when the session is unavailable.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate for parameter meaning. It clarifies that base and compare are the two data sets, but it gives no explanation of `by` or `criterion`. These optional parameters are left ambiguous despite being important for controlling how the comparison is performed.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb and resource: 'Run PROC COMPARE between two data sets' and clearly states what the tool returns: a structured diff with identity, data-vs-metadata distinction, and difference kinds. It distinguishes itself from sibling tools like run_sas and describe_dataset by focusing on comparison-based validation.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives a clear primary use case: 'the primary way to validate that a rewrite produces the same result as the original.' This provides meaningful context for when to choose this tool, though it does not explicitly name alternatives or state when not to use it.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

describe_datasetA
Read-only

Return the columns of a SAS data set with type, length, format, informat, and label, plus the row count. Call this before writing code against a table you have not already inspected.

ParametersJSON Schema
NameRequiredDescriptionDefault
tableYes
librefYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already provide readOnlyHint=true, and the description aligns by describing a non-mutating inspection operation. It adds useful behavioral context by specifying the returned information and framing the tool as a preliminary inspection step. No contradiction.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences with no filler. The primary output is stated first, and the second sentence provides a practical usage guideline. Every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a small read-only tool with an output schema, the description covers what it returns and when to call it. The main gap is parameter semantics, but the simple required parameters and the output schema keep it sufficiently complete for invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema documentation coverage is 0%, and the description does not explain what 'libref' and 'table' mean beyond the phrase 'SAS data set.' An agent must rely on parameter names and SAS domain knowledge to understand that libref is the library reference and table is the dataset name.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific action ('Return the columns of a SAS data set') and a specific resource, enumerating the metadata fields plus row count. This distinguishes it from sibling tools like list_datasets or sample_rows by describing a metadata introspection operation.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives an explicit usage recommendation: 'Call this before writing code against a table you have not already inspected.' It does not name alternative tools or explicitly state when not to use it, so it stops short of full routing guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

download_from_sasA

Copy a file from the SAS server's filesystem to this machine, over the SAS connection. Works even when the two share no filesystem -- for example a workbook written by PROC EXPORT on SAS ODA. Returns the local path, which the user can open. Files land in this server's transfer directory; arbitrary local paths are not accepted.

ParametersJSON Schema
NameRequiredDescriptionDefault
overwriteNo
local_nameNo
remote_pathYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With annotations all false, the description carries the burden and adds meaningful behavior: it returns the local path, writes into the server's transfer directory, and rejects arbitrary local paths. It also clarifies that the operation is a copy over the SAS connection, consistent with destructiveHint=false, and no contradiction exists.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four short sentences, with the core action and destination front-loaded. Every sentence earns its place: what it does, when it works, what it returns, and where files are placed.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description covers the essential workflow, return value, and a critical path restriction. Because an output schema exists, omitting a return format is acceptable; it could add overwrite behavior, but the remaining gaps are minor.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate. It clarifies that remote_path is a file on the SAS server's filesystem and constrains local destination behavior (transfer directory only, no arbitrary paths), but it does not mention overwrite or explain the local_name parameter explicitly.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: 'Copy a file from the SAS server's filesystem to this machine, over the SAS connection.' It makes the transfer direction unmistakable and clearly differentiates this tool from upload_to_sas and list_sas_files.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives clear contextual guidance: it is the right choice when a file must cross from SAS to this machine, especially when there is no shared filesystem (e.g., PROC EXPORT output on SAS ODA). It does not explicitly name exclusion conditions or alternatives, but the transfer direction and cross-filesystem note are enough for an agent to select it appropriately.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_last_logA
Read-only

Return the full raw SAS log from the most recent submit. Use only when the triaged output from run_sas was not enough to diagnose the problem, since logs consume a lot of context.

ParametersJSON Schema
NameRequiredDescriptionDefault
from_endNo
max_linesNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already mark readOnlyHint=true, so the safety profile is covered. The description adds behavioral context: the log is 'full raw' (not triaged), it's from the 'most recent submit', and it warns that logs 'consume a lot of context' — a useful cost signal beyond the annotations. It does not describe output format, but that is covered by the output schema.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences with zero waste. The primary action is front-loaded, and the advisory note is concise. Every word earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool is simple (two optional parameters), and an output schema exists, but the complete lack of parameter guidance is a notable gap. The description clearly states purpose, usage, and cost, so the agent can decide when to call it, but may not know how to tailor calls (e.g., max_lines) without additional information.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters1/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the schema provides no parameter documentation. The description does not mention 'from_end' or 'max_lines' at all, leaving the agent to guess their meaning. While the names are somewhat self-explanatory, the tool description adds no value beyond the schema, failing to compensate for the low coverage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: 'Return the full raw SAS log from the most recent submit.' It clearly distinguishes itself from run_sas by contrasting the raw log with the 'triaged output' from run_sas, so an agent can tell them apart.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly states when to use this tool: 'Use only when the triaged output from run_sas was not enough to diagnose the problem.' It also gives a reason (logs consume a lot of context), which helps the agent avoid unnecessary calls. This directly addresses usage guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_datasetsA
Read-only

List the data sets in a SAS library, with row counts, column counts, and modification dates.

ParametersJSON Schema
NameRequiredDescriptionDefault
librefYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already provide readOnlyHint=true, and the description adds useful context by specifying exactly what the listing includes (row counts, column counts, modification dates). This goes beyond the schema and gives the agent a clearer picture of the tool's output behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single, front-loaded sentence with no filler. Every word contributes to the tool's purpose.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description covers the core action and details of the output, and an output schema is present to define return format. It does not mention practical caveats like requiring an active session or behavior on invalid libref, but these are minor for a simple read-only listing tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate. It indirectly describes the only parameter (libref) by mentioning 'SAS library', but it does not explicitly define libref as the library name or clarify any formatting requirements.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb ('List'), a clear resource ('data sets in a SAS library'), and adds distinguishing detail (row counts, column counts, modification dates). This makes it easy to differentiate from siblings like list_libraries (libraries) and describe_dataset (single dataset).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage when an agent needs an inventory of datasets in a library, but it does not explicitly state when to use it versus alternatives like list_libraries or describe_dataset, nor does it mention any prerequisites or exclusions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_librariesA
Read-only

List assigned SAS libraries with path, engine, whether SAS considers them read-only, and whether this server's policy allows writing to them.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The readOnlyHint annotation already establishes this as a safe read operation, and the description aligns with that. It adds meaningful behavioral nuance by distinguishing between what SAS considers read-only and what the server policy permits writing to, which is valuable context beyond the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single, well-structured sentence communicates the action, resource, and returned fields without unnecessary words. The key verb and resource are front-loaded, making the description scannable and efficient.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given that the tool is parameterless, has an output schema, and is annotated as read-only, the description provides sufficient context for correct invocation. The mention of assigned libraries and policy details helps the agent understand the scope and semantics without needing additional explanation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool has zero parameters, so there are no parameter semantics to clarify. The description appropriately focuses on what the tool returns rather than on inputs, and no parameter documentation burden exists.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states that the tool lists assigned SAS libraries and enumerates the specific attributes returned: path, engine, SAS read-only status, and server policy write access. This is a specific verb+resource combination that distinguishes it from sibling tools like list_datasets, which operate on datasets rather than libraries.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description makes the tool's purpose clear, so an agent can infer it is appropriate when needing an overview of available libraries. However, it does not explicitly mention when not to use it or contrast it with sibling tools such as list_datasets or describe_dataset, leaving usage boundaries implied rather than stated.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_sas_configsA
Read-only

List the SAS configurations available in the user's SASPy setup, with the access method and target server for each. Call this when connecting reports that a configuration must be chosen, or when the user mentions a specific SAS environment by name.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.3/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and openWorldHint=false, so the read-only nature is established. The description adds value by mentioning the output contains access method and target server, which is useful context. There is no contradiction with annotations, but the description does not disclose any other behavioral traits beyond what annotations provide.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences with no redundancy. The first sentence states the core function and output, the second gives usage guidance. Every word earns its place; it's tightly written and well-structured.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a parameter-less tool with an output schema (present), the description fully covers purpose and usage. There is no missing information that would impede an agent from correctly deciding when to call this tool and what to expect from it.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool has zero parameters, and the input schema is empty with 100% coverage. Per the baseline for 0 params, the score is 4. The description does not need to elaborate on parameter semantics.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the verb 'list' and the resource 'SAS configurations', and specifies the information returned (access method and target server). It distinguishes this tool from siblings like use_sas_config (which selects a config) and list_sas_files (which lists files).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides clear usage context: 'Call this when connecting reports that a configuration must be chosen, or when the user mentions a specific SAS environment by name.' It does not explicitly list alternatives or exclusions, but the trigger conditions are concrete and actionable.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_sas_filesA
Read-only

List a directory on the SAS server's filesystem. Use it to confirm where a step actually wrote its output before downloading.

ParametersJSON Schema
NameRequiredDescriptionDefault
pathYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The readOnlyHint annotation already signals safety, and the description adds useful context about the tool's role in verifying actual output locations on the server filesystem. It does not contradict the annotations and gives enough behavioral framing for a read-only list operation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two sentences with no filler. The first sentence states the core function, and the second provides actionable usage guidance. Every word earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple single-parameter read-only tool with an output schema present, the description covers what the tool does and when to use it. The only notable gap is the lack of path specification details, but the presence of an output schema mitigates the need for describing return values.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, and the description does not explain the 'path' parameter's expected format, whether it is absolute/relative, or any constraints. Saying 'directory on the SAS server's filesystem' is only minimally helpful; the description should compensate for the lack of schema documentation but does not.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb ('List') and resource ('a directory on the SAS server's filesystem'), clearly distinguishing this from siblings like list_libraries and list_datasets, which operate on SAS logical structures rather than the filesystem. It also connects the tool to a concrete workflow: confirming where a step wrote output before downloading.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The second sentence gives a clear use case: 'Use it to confirm where a step actually wrote its output before downloading.' This provides context for when to invoke the tool, though it does not explicitly state when not to use it or name alternatives.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

reset_sessionA
Destructive

Delete every data set in WORK to clear accumulated state. Librefs and the connection itself are preserved. Use when earlier intermediate tables are causing confusion.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=true and readOnlyHint=false, so the destructive nature is known. The description adds valuable behavioral detail beyond the annotation: it specifies that librefs and the connection are preserved, and clarifies the exact scope (only WORK datasets). This extra context helps the agent understand side effects.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two concise sentences, with the action and scope front-loaded. Every word earns its place: the operation, what is preserved, and the rationale for use. No redundancy or filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a zero-parameter destructive tool, the description covers purpose, scope, preservation behavior, and when to use it. The output schema exists, so no need to explain return values. The description is complete for an agent to call it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool has zero parameters, so the baseline is 4. The description adds no parameter-specific information, but none is needed. Schema coverage is trivially 100% since there are no parameters.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action (delete every data set in WORK) and the resource (WORK library), plus the purpose (clear accumulated state). It is distinct from sibling tools like run_sas or session_status, leaving no ambiguity about what the tool does.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly gives a use case: 'Use when earlier intermediate tables are causing confusion.' This provides clear context for when to invoke the tool. It does not mention alternatives or when not to use, but the guidance is sufficient for an agent to decide appropriately.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

run_sasA

Submit SAS code to the live session and return a triaged result: status (ok / suspicious / error), extracted errors and warnings, the NOTEs that mean the code ran but the answer may be wrong, per-step row counts, and the listing output. Writes outside WORK are blocked by policy. The session keeps state between calls.

ParametersJSON Schema
NameRequiredDescriptionDefault
codeYes
include_logNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations provide no positive safety hints (readOnlyHint is false and destructiveHint is false), so the description carries the burden. It adds important behavioral context by stating 'Writes outside WORK are blocked by policy' and 'The session keeps state between calls,' plus it explains the meaningful triage categories. It could mention side effects on WORK data more explicitly, but the policy boundary significantly clarifies risk.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is compact and well-structured: purpose and output details come first, followed by the safety constraint and statefulness note. Every sentence contributes useful information without repetition or filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a code-execution tool, the description covers the core action, output shape, safety boundary, and session statefulness, and an output schema handles return-value details. The main gap is the undocumented include_log parameter and the lack of explicit relationships to session-management siblings, but the overall picture is sufficient for correct use in most cases.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must explain the parameters. The 'code' parameter is covered implicitly by 'Submit SAS code,' but 'include_log' is never described beyond its schema title and default value. An agent gets little help understanding when or why to set include_log to true.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description begins with a specific verb and target: 'Submit SAS code to the live session.' It then details what the tool returns, including triaged status, errors/warnings, NOTEs, row counts, and listing output. This clearly distinguishes it from siblings like get_last_log or run_sas_tests, even without naming them.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The intended use is implied: when you need to run SAS code against the live session, use this tool. However, there is no explicit guidance about when to prefer run_sas over run_sas_tests, or when not to use it, and no alternatives are mentioned.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

run_sas_testsA

Run SAS code with the assertion macro library available, and return each assertion's pass/fail result alongside the usual log triage. Available macros: %assert_exists(ds), %assert_rows(ds, n), %assert_not_empty(ds), %assert_no_missing(ds, var), %assert_unique(ds, key), %assert_equal_datasets(base, compare), and %assert_condition(condition, detail=...). Use this to validate code you have written.

ParametersJSON Schema
NameRequiredDescriptionDefault
codeYes
include_logNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A3.8/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description discloses the key behavioral trait: assertions are returned as pass/fail results along with log triage, and the assertion macro library is available. However, annotations provide no safety profile (all hints false), and the description does not address side effects, session state, error behavior, or whether execution is isolated.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The opening sentence front-loads the purpose and return behavior, and the macro list is useful despite being somewhat lengthy. Every element earns its place, though the macro enumeration could be trimmed or summarized without much loss.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, the return values do not need full explanation in the description. The description is complete enough for selecting and invoking the tool: it covers purpose, available macros, and the intended validation use case. Minor gaps remain around `include_log` and interaction with session state, but these are not blocking.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate. It implicitly clarifies that `code` holds SAS code with assertions, but `include_log` is never mentioned or explained. The description adds meaning for only one of the two parameters and leaves the boolean parameter's behavior to inference.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names a specific verb and resource: 'Run SAS code' with the assertion macro library available, and states the distinct return of assertion pass/fail results alongside log triage. This clearly separates it from sibling tools like run_sas, which lacks the assertion-specific output.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives clear context: 'Use this to validate code you have written.' It lists the available assertion macros, so an agent knows what kinds of validation are supported. It does not explicitly say when not to use it or name run_sas as the alternative for plain execution, but the intended use case is reasonably clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

sample_rowsA
Read-only

Return the first N rows of a SAS data set as records, to inspect actual values, coding schemes, and missingness.

ParametersJSON Schema
NameRequiredDescriptionDefault
nNo
tableYes
librefYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The readOnlyHint annotation already declares the operation is safe, and the description's 'Return' is consistent with that. Beyond the annotation, the description adds that the result is a prefix of rows ('first N') and that it exposes raw content like actual values and missingness, helping the agent anticipate the output nature.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, action-first sentence with no filler. It states what the tool returns and why, earning every word.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a low-complexity, read-only sampling tool with an output schema and readOnlyHint annotation, the description covers the essential invocation intent and expected return. The main gap is explicit libref/table semantics, but the schema names both as required string fields, so an agent can still invoke the tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With schema description coverage at 0%, the description carries the burden of explaining parameters. It clarifies that 'n' is the number of rows to return, but it does not explain 'libref' or 'table' beyond naming a SAS data set generally. The two required parameters remain under-specified.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb ('Return'), a concrete resource ('first N rows of a SAS data set as records'), and an explicit purpose ('inspect actual values, coding schemes, and missingness'). It is clearly distinguishable from sibling tools like describe_dataset, which would describe metadata rather than raw data.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description communicates when to use this tool: when an agent needs to inspect actual data values, coding schemes, or missingness. It does not explicitly name alternatives or exclusion conditions, but the context is clear enough for selection among the listed siblings.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

sas_doctorA
Read-only

Diagnose SASPy configuration without connecting: config file and connection method, Java runtime for IOM, ~/.authinfo presence and permissions, ODA hostname validity, network reachability, and encoding. Run this first whenever a connection fails.

ParametersJSON Schema
NameRequiredDescriptionDefault
probe_networkNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, and the description adds relevant behavioral context by stating the tool diagnoses 'without connecting' and listing the diagnostic areas it inspects. There is no mutation implied and no contradiction with annotations. It does not describe output details, but an output schema exists to carry that burden.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is compact and front-loaded: one dense sentence enumerates the diagnostic scope, and a short imperative sentence gives usage guidance. There is no filler, and every phrase adds distinctive information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a read-only diagnostic tool with an output schema, the description covers scope and usage well: it names the diagnostic categories, says to run it first on connection failure, and clarifies it does not connect. The only notable gap is that the optional probe_network parameter is only implied rather than explicitly tied to the parameter name, but the schema and default mitigate this.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate for the single probe_network parameter. The phrase 'network reachability' maps plausibly to probe_network, but the parameter is never named and its effect when set to false is left to inference. The schema's default helps, but the description adds only partial semantic value.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb ('Diagnose') and a clear resource ('SASPy configuration'), then enumerates exactly what is checked: config file, connection method, Java runtime, .authinfo, ODA hostname, network reachability, and encoding. It also distinguishes itself from siblings with 'Run this first whenever a connection fails,' so an agent can separate it from run_sas or session_status.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives an explicit when-to-use instruction: 'Run this first whenever a connection fails.' It also clarifies that it operates 'without connecting,' which sets expectations for pre-connection diagnostics. It does not name alternatives or explicitly state when not to use it, so it stops short of a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

session_statusA
Read-only

Report whether a SAS session is live, the SAS version and encoding, the assigned librefs, the data sets currently in WORK, and the active write policy. Useful for reorienting after a long conversation.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.3/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The annotations already declare readOnlyHint=true, and the description's verb 'Report' aligns with that. The description adds useful output-scope context, such as the active write policy and WORK datasets, but does not disclose deeper behavioral details like connection behavior or side effects; the read-only annotation lowers the burden and the description does not contradict it.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two sentences with no wasted words. The first sentence front-loads the complete list of reported items, and the second sentence adds a practical use case. Every part earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no parameters and an output schema available, the description covers the essential context: what the tool reports and when to use it. Nothing an agent needs to decide whether to invoke this tool is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool has zero parameters, so there is nothing for the description to clarify beyond what the schema already shows. Baseline 4 applies because no parameter documentation is needed.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb ('Report') and clearly identifies the resource: the SAS session. It enumerates the exact facets reported (liveness, version, encoding, librefs, WORK datasets, write policy), which distinguishes it from siblings like list_libraries and list_datasets that cover only subsets.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly states when to use it: 'Useful for reorienting after a long conversation.' It provides clear context but does not explicitly mention alternatives or when not to use it, so it stops short of the strongest guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

upload_to_sasA

Send a file from this server's transfer directory to the SAS server's filesystem, over the SAS connection. Only files already in the transfer directory can be sent; to upload something else, ask the user to copy it there first.

ParametersJSON Schema
NameRequiredDescriptionDefault
overwriteNo
local_nameYes
remote_pathYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A3.8/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already communicate non-read-only, non-idempotent, non-destructive behavior. The description adds useful context about the transfer-directory constraint and the SAS connection, but does not disclose overwrite behavior, collision handling, or failure modes. With annotations present, the bar is lower, and the description provides reasonable but not rich extra context.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences with no filler: the first states the operation, the second states the boundary and fallback. The key constraint is front-loaded, and every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description covers the source constraint and the transfer direction, and an output schema is present. However, it omits important operational details such as remote_path format, what overwrite=true actually does, and what happens on failure, leaving an agent to guess in realistic scenarios.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must carry the burden of explaining parameters. It clarifies that local_name refers to a file in the transfer directory, but remote_path and overwrite semantics are not addressed at all. The schema only provides names and a default, which is insufficient for reliable invocation.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific action—'Send a file from this server's transfer directory to the SAS server's filesystem'—with clear directionality, source, and destination. It distinguishes itself from sibling tools like download_from_sas by making the upload direction explicit.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives clear context and a hard precondition: only files already in the transfer directory can be sent, and other files must be copied there first. It does not explicitly name alternatives, but the constraint and fallback instruction effectively guide an agent on when this tool applies.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

use_sas_configA
Destructive

Select which SAS configuration to connect to, by name. Ends any current SAS session, so WORK data sets and librefs from the previous configuration are lost. Use when the user names a SAS environment, or after list_sas_configs shows several.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Discloses a critical side effect: 'Ends any current SAS session, so WORK data sets and librefs from the previous configuration are lost.' This goes beyond the destructiveHint annotation by specifying exactly what is lost, which is essential for an agent to warn the user or verify intent.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences with no filler. The purpose is front-loaded, followed by the side effect, then usage guidance. Every sentence earns its place and is highly efficient.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a single-parameter, destructive tool with an output schema, the description covers purpose, usage, and side effects. No additional information is needed for an agent to invoke it correctly; the side-effect warning is particularly valuable for safety.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 0% schema description coverage, the description compensates by implying the 'name' parameter is the configuration name ('by name', 'names a SAS environment'). It does not explicitly state 'name' is the config name, but the context is strong enough for an agent to infer it. Slight deduction for not being fully explicit.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific action (select/connect) on a specific resource (SAS configuration) by name, which clearly distinguishes it from siblings like list_sas_configs (listing) and run_sas (execution). It is not a tautology and provides precise scope.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly states when to use: 'Use when the user names a SAS environment, or after list_sas_configs shows several.' This gives direct invocation conditions and references a sibling tool for context, making the decision clear without ambiguity.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

TDQS

A4/5.0
Disambiguation4/5

Most tools target a distinct resource and action: config selection, code execution, dataset metadata, file transfer, and comparison. A few overlapping boundaries exist—session_status overlaps with list_libraries/list_datasets for a quick overview, and run_sas vs. run_sas_tests both submit code—but the descriptions make the intended use clear.

Naming Consistency4/5

The majority follow a clear verb_noun pattern such as list_datasets, describe_dataset, compare_datasets, and download_from_sas. The exceptions are session_status and sas_doctor, which are noun-led and break the otherwise predictable scheme.

Tool Count4/5

Sixteen tools is slightly above the typical 3–15 sweet spot, but each tool maps to a distinct part of the SAS workflow: connection management, session state, code execution, file transfer, metadata inspection, and validation. The count feels justified rather than bloated.

Completeness4/5

The surface covers the core SAS lifecycle well: configure/connect, inspect session and datasets, run code, retrieve logs, transfer files, compare tables, and run tests. Minor gaps exist—no explicit disconnect tool or direct file deletion—but these do not create dead ends since run_sas and session management cover most of them.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    A
    maintenance
    Provides sandboxed code execution for AI agents with support for Python, JavaScript, and shell commands. Includes comprehensive safety features like destructive pattern blocking, timeout protection, and restricted file access for secure production use.
    22
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables AI agents to detect development environments, install missing tools, scan local code projects, and generate visual reports.
    16
    MIT
  • F
    license
    Not graded
    quality
    D
    maintenance
    Acts as the 'Hands and Eyes' for an Autonomous AI Agent, bridging Large Language Models and your local development environment to enable safe file manipulation, context reading, command execution, and documentation verification.
    2

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/matise-joe-norc/sas-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server