Skip to main content
Glama
dbdave

SSAS MCP Server

by dbdave
README.md
# SSAS MCP Server

A read-only [Model Context Protocol](https://modelcontextprotocol.io) server for querying
**SQL Server Analysis Services** — both **multidimensional cubes (MDX)** and **tabular
models (DAX)** — with **Windows Integrated Security** (Kerberos/NTLM, no passwords).

Companion to [mssql_mcp_server](https://github.com/dbdave/mssql_mcp_server), but for the
OLAP side of the house.

## Features

- **`list_metadata`** — discover a cube/model's measures, dimensions and hierarchies
  (via `MDSCHEMA_*` DMVs, which work for both model types), so the agent never guesses
  bracketed unique names. The overview stays compact — measures, dimension names and
  multi-level user hierarchies; pass `dimension="[Dim Event]"` to drill into one
  dimension's full attribute hierarchies and levels (a whole cube's attribute list can
  run to tens of thousands of tokens).
- **`execute_query`** — run an MDX (`SELECT`/`WITH`) or DAX (`EVALUATE`/`DEFINE`) query
  and get a flattened JSON table back.
- **`execute_dmv`** — guarded passthrough for `SELECT ... FROM $SYSTEM.*` schema rowsets
  (`MDSCHEMA_*`, `TMSCHEMA_*`, `DISCOVER_*`) for deeper introspection.
- **Read-only by construction** — statements that don't start with
  `SELECT`/`WITH`/`EVALUATE`/`DEFINE` are rejected, XMLA payloads are rejected, and there
  is no DDL/process surface at all.
- **Row cap + query timeout** on every call so a runaway crossjoin can't flood the
  context window.

## Requirements

Windows-only by construction (the server drives ADOMD.NET via pythonnet):

1. **Windows**, domain-joined, with network access to the SSAS instance
   (default instance = TCP 2383).
2. The Windows account running the server has **Read** access to the SSAS database
   (role membership). Integrated auth means "whoever runs the process".
3. **ADOMD.NET client libraries** — ships with SSMS, or install the
   [Analysis Services client libraries](https://learn.microsoft.com/en-us/analysis-services/client-libraries)
   redistributable. Typically lands in `C:\Program Files\Microsoft.NET\ADOMD.NET\160`.
4. **Python 3.11+**

## Installation

```powershell
git clone https://github.com/dbdave/mssas_mcp_server
cd mssas_mcp_server
pip install -e .
```

Smoke-test connectivity before wiring up MCP (if this fails it's network/auth/ADOMD
install, not the server):

```powershell
python test_connection.py <server> <catalog>
```

## Configuration

| Variable | Required | Default | Notes |
|---|---|---|---|
| `SSAS_SERVER` | yes | — | Host, `host\instance`, or an `http(s)://.../msmdpump.dll` URL |
| `SSAS_CATALOG` | yes | — | SSAS database name |
| `SSAS_DEFAULT_CUBE` | no | — | Cube/model `list_metadata` uses when none is given |
| `SSAS_ROW_LIMIT` | no | `10000` | Hard cap on returned rows |
| `SSAS_QUERY_TIMEOUT` | no | `60` | Per-query timeout, seconds |
| `SSAS_ADOMD_DLL_DIR` | no | auto-detected | Folder containing `Microsoft.AnalysisServices.AdomdClient.dll` |

Authentication is always Windows Integrated Security (`Integrated Security=SSPI`) —
no credentials in config.

## MCP registration (Claude Code / Claude Desktop)

```json
{
  "mcpServers": {
    "ssas-cube": {
      "command": "python",
      "args": ["-m", "ssas_mcp.server"],
      "env": {
        "SSAS_SERVER": "my-ssas-host",
        "SSAS_CATALOG": "My_Cube_Db",
        "SSAS_DEFAULT_CUBE": "Sales"
      }
    }
  }
}
```

One registered server targets one SSAS database. To use both a multidimensional and a
tabular instance, register the server twice with different `SSAS_SERVER`/`SSAS_CATALOG`
env blocks — the query language is chosen per call (`execute_query` accepts MDX or DAX,
and the engine itself only accepts the language matching the model type).

## Example usage

Multidimensional (MDX):

```mdx
SELECT NON EMPTY { [Measures].[Tickets Issued] } ON COLUMNS,
       NON EMPTY { [Sales Item Fact Ordered Date].[Calendar].[Year Name].MEMBERS } ON ROWS
FROM [Sales]
```

Tabular (DAX):

```dax
EVALUATE SUMMARIZECOLUMNS('Date'[Year], "Total Sales", [Total Sales])
```

DMV introspection:

```sql
SELECT [MEASURE_NAME], [MEASUREGROUP_NAME] FROM $SYSTEM.MDSCHEMA_MEASURES WHERE [CUBE_NAME] = 'Sales'
SELECT * FROM $SYSTEM.TMSCHEMA_MEASURES  -- tabular models
```

## Result format

Tools return JSON:

```json
{
  "columns": ["[Sales Item Fact Ordered Date].[Calendar].[Year Name].[MEMBER_CAPTION]", "[Measures].[Tickets Issued]"],
  "rows": [["2025", 123456], ["2026", 98765]],
  "row_count": 2,
  "truncated": false
}
```

Cells can be null and columns can be mixed-type — MDX cellsets are flattened
defensively (nulls preserved, `Decimal` → float, `DateTime` → ISO string).

## Tests

```powershell
pip install pytest
pytest tests/
```

## License

MIT

TDQS

A4.7/5.0

Scored across 3 tools

Disambiguation5/5

Each tool serves a distinct purpose: execute_dmv for DMV system queries, execute_query for MDX/DAX against the cube/model, and list_metadata for exploring metadata structure. No functional overlap.

Naming Consistency5/5

All tools follow a consistent verb_noun snake_case pattern: execute_dmv, execute_query, list_metadata. The naming is predictable and unambiguous.

Tool Count5/5

Three tools cover the essential read-only query and metadata exploration workflow for SSAS, with no extraneous or missing operations. The count is well-scoped for the domain.

Completeness5/5

The tool set provides complete coverage for the stated purpose: listing metadata to discover names, executing queries via MDX/DAX or DMV, and handling cube/model selection. No obvious gaps.

Maintenance

ActivitySlowing
ResponsivenessNo issues