In about 20 minutes you will:

  1. run eMondrian Community locally with sample data,
  2. query a ready-made cube from the browser, Excel, Power BI and an AI agent,
  3. connect your own database and publish your first cube — by hand or with an AI agent.
%%{init: {"flowchart": {"curve": "linear"}}}%%
flowchart LR
  excel["Excel"] -->|XMLA · MDX| em
  pbi["Power BI"] -->|XMLA · DAX| em
  ai["AI agent"] -->|MCP| em
  em["<b>eMondrian</b><br/>semantic model"]:::core -->|SQL| db[("ClickHouse /<br/>your database")]
What you useNeeds a license key?
Excel, MDX, OLAP Client, Schema Editor, Catalog EditorNo — free, open source
Power BI (DAX module)Yes — free 30-day evaluation key (one key for DAX and MCP)
AI agents (MCP module)Yes — the same evaluation key

Local evaluation only

Community ships with no authentication: anyone who can reach the server can query data, edit schemas and read logs. Run it on localhost or a trusted network only.


1. Prerequisites

  • Git
  • Windows 10/11 or a supported Linux distribution
  • Administrator / sudo rights — to install Docker and start containers
  • Port 80 free — or choose another port (see below)
  • About 2 GB free disk space and ~700 MB of downloads on the first run
  • Excel (Windows) and/or Power BI Desktop to connect BI tools
  • An MCP client (Claude Code, Claude Desktop, …) to connect AI agents

Docker is installed automatically by the setup script if it isn’t there yet.


2. Install and start

git clone https://github.com/eMondrian/emondrian-community.git
cd emondrian-community

Linux

./setup.sh

If the script has just installed Docker, your user isn’t in the docker group yet: log out and back in (or run newgrp docker) and run the script again.

Windows (PowerShell)

powershell -ExecutionPolicy Bypass -File .\windows-setup.ps1

If WSL 2 has to be installed or updated, Windows may need a restart. After restarting, run the same command again — re-running is safe.

The first run takes a few minutes (mostly downloads). The script starts the containers and loads a sample flight-data set into ClickHouse.

Port 80 already in use? Before running the script, copy .env.example to .env and set:

EMONDRIAN_PORT=8081

All addresses below then use that port, e.g. http://localhost:8081/xmla.

Check that it works

Open http://localhost — you should see the eMondrian main page.

AddressWhat it is
http://localhostMain page: links to tools, installed licenses, license activation
http://localhost/xmlaXMLA endpoint for Excel, Power BI and other clients
http://localhost/client/OLAP Client (layout builder, MDX editor, pivot table)
http://localhost/schema-editor/Schema Editor — cubes, dimensions, measures and roles of a schema
http://localhost/catalog-editor/Catalog Editor — data sources and catalogs the server publishes
http://localhost/logs/Server logs
http://localhost/emondrian/mcp/sseMCP endpoint for AI agents

3. Explore the sample data

Two catalogs are ready after setup:

  • FoodMart — the classic Mondrian retail demo (embedded HSQLDB).
  • OnTime — US domestic flights from the Bureau of Transportation Statistics, in ClickHouse. January 2022 is loaded (~537,000 rows).

Open the OLAP Client at http://localhost/client/ and connect — the server address is filled in. Choose catalog OnTime, type this query into the MDX editor and click Run:

SELECT
  {[Measures].[Flights], [Measures].[Cancellation Rate], [Measures].[Avg Arr Delay]} ON COLUMNS,
  [Airline].[Airline].Members ON ROWS
FROM [OnTime (attributes)]

You get flights, cancellation rate and average arrival delay per airline — calculated by eMondrian from ClickHouse.

Load more OnTime data
./clickhouse/scripts/setup-ontime.sh --year 2022              # one whole year
./clickhouse/scripts/setup-ontime.sh --year 2022 --months 1,2,3
./clickhouse/scripts/setup-ontime.sh --full                   # every year — very large
docker compose up -d

Downloaded CSV files stay in clickhouse/datasets/ontime/; delete them after import if you need the space.


4. Connect Excel (free)

  1. In Excel: Data → Get Data → From Database → From Analysis Services.
  2. Server name: http://localhost/xmla
  3. Log on credentials: keep Use Windows Authentication. Click Next.
  4. Select the database OnTime and the cube OnTime (attributes). Click Next, then Finish.
  5. Choose PivotTable Report and click OK.
  6. Drag Flights and On-Time Rate to Values, Airline to Rows, Time to Columns.

That’s a live PivotTable on ClickHouse: every change in the PivotTable sends an MDX query to eMondrian.


5. Connect Power BI (DAX module)

Power BI talks to eMondrian in DAX, so it needs the DAX module. It is included in the Community download and unlocked by a free 30-day evaluation key. The same key also unlocks the MCP module (section 6).

5.1 Get and activate an evaluation key

  1. Request a key at https://emondrian.com/license — it arrives by email and looks like TRIAL-0123456789ABCDEF (TRIAL- followed by 16 characters). It is valid for 30 days and unlocks the DAX and MCP modules.
  2. Open http://localhost, paste the key into License code under Activate a license in the License section and click Activate license. The key appears in the list of installed licenses above, marked Active. No internet on the server? Download the license file on the license page and use Upload license file (No internet access) instead. The file picker shows .tar files — select the downloaded file as is.

The key takes effect immediately — no restart needed on a server that had no valid key.

When the key expires

DAX and MCP stop; Excel and MDX keep working. Power BI loses even its field list, because Power BI reads the model metadata through the DAX module. Request an extension or a commercial license, activate it, then run docker compose restart eMondrian — a server caches a valid key until restart.

5.2 Connect

  1. In Power BI Desktop: Get data → Analysis Services.
  2. Server: http://localhost/xmla · Database: OnTime (optional).
  3. Select Connect live and click OK.
  4. Pick the cube and build a visual — e.g. a bar chart of Flights by Airline.

To see the DAX that Power BI sends, open Optimize → Performance analyzer, start recording and refresh a visual.

Microsoft support

Power BI connects through the Analysis Services connector. Microsoft does not officially support third-party servers this way. We test each Power BI release — if something breaks, please open an issue.


6. Connect an AI agent (MCP module)

eMondrian Community includes an MCP server. AI agents — Claude Code, Claude Desktop and other MCP clients — can list your catalogs, read and write schemas, and query the semantic model with MDX and DAX.

The MCP module is included in the Community download and unlocked by the same evaluation key as DAX. If you activated a key in 5.1, MCP is already enabled — otherwise do that first.

Why connect an agent to the semantic model instead of the database? The agent works with business definitions — Revenue, On-Time Rate, Region — that are already defined once, instead of guessing joins and formulas from raw tables. Excel, Power BI and the agent get the same numbers.

6.1 The endpoint

The MCP module is loaded automatically at startup and served on the same port as everything else:

http://localhost/emondrian/mcp/sse

Transport: HTTP + SSE.

Replacing a key

A valid key is cached until restart. If you replace an active key (for example, after an extension), run docker compose restart eMondrian. A server that had no valid key picks up a new one without a restart.

6.2 Connect your MCP client

Claude Code

claude mcp add --transport sse emondrian http://localhost/emondrian/mcp/sse

Claude Desktop — Claude Desktop starts local (stdio) servers, so use the mcp-remote bridge. Add to claude_desktop_config.json and restart Claude Desktop (we haven’t tested this setup ourselves yet — let us know in GitHub issues if it works for you):

{
  "mcpServers": {
    "emondrian": {
      "command": "npx",
      "args": ["-y", "mcp-remote", "http://localhost/emondrian/mcp/sse"]
    }
  }
}

Other clients — any MCP client that supports the SSE transport: point it to the URL above.

6.3 Try it

Ask your agent:

  • “Which catalogs and cubes are on this server?” → FoodMart, OnTime
  • “In the OnTime catalog, which airline had the highest cancellation rate in January 2022?”
  • “Compare average arrival delay by day of week and explain the pattern.”
  • “Run this MDX on catalog FoodMart: SELECT {[Measures].[Org Salary]} ON 0 FROM [HR]”

The agent reads the schema, writes the MDX itself, runs it and explains the result.

DAX through MCP

execute_query also accepts DAX (queries starting with EVALUATE or DEFINE). For DAX, name the cube when the catalog has more than one (FoodMart has six; OnTime has one, so no cube is needed). Write measures table-qualified: EVALUATE ROW("Org_Salary", 'HR'[Org Salary]) on cube HR, not [Org Salary].

6.4 Available tools

ToolWhat it does
list_catalogsLists catalogs declared in datasources.xml
get_schemaReturns the schema XML of a catalog
execute_queryRuns MDX or DAX on a catalog (DAX detected by leading EVALUATE / DEFINE). Optional cube argument — required for DAX when the catalog has more than one cube
validate_schemaChecks schema XML for problems the engine doesn’t report
save_schemaOverwrites the schema of a catalog (validated first)
get_propertiesShows the server’s mondrian.properties
read_logsLists log files or shows the end of one
get_cube_authoring_guideGuide for writing and editing schemas
list-cubes, run-mdx-queryLegacy tools for a single fixed connection (need -Demondrian.mcp.connectString)

Unauthenticated, and not read-only

In Community the MCP endpoint has no authentication. Anyone who can reach the server can rewrite schemas (save_schema) and read server logs through MCP. Keep it on localhost or a trusted network. Large query results are returned in full — there is no row limit, so ask the agent for aggregated results rather than raw detail.

Using AI agents in production?

Authentication, per-user access (the agent sees only what the user may see), an audit log of agent queries and query limits are planned for eMondrian Enterprise — see pricing.


7. Connect your own database

Out of the box the image includes JDBC drivers for ClickHouse and PostgreSQL (and HSQLDB for FoodMart). Other databases need their JDBC driver added — see 7.5.

7.1 Add a catalog

Catalogs are defined in datasources.xml in the project folder. Add a <Catalog> inside the existing <Catalogs> element:

<Catalog name="MySales">
  <DataSourceInfo>Provider=mondrian;Jdbc=jdbc:clickhouse://my-clickhouse-host:8123/mydb?user=myuser&amp;password=mypassword;JdbcDrivers=com.clickhouse.jdbc.ClickHouseDriver</DataSourceInfo>
  <Definition>/WEB-INF/schema/MySales.xml</Definition>
</Catalog>

Order matters

Write <DataSourceInfo> before <Definition>. The parser reads them in order; reversed, your connect string is silently dropped.

  • & in the JDBC URL must be written as &amp; (it’s XML).
  • The schema/ folder of the project is mounted as /WEB-INF/schema/, so schema/MySales.xml on disk is /WEB-INF/schema/MySales.xml in <Definition>.
  • Database on the same machine? Inside the container, localhost is the container itself. Use host.docker.internal instead. On Linux, also add to the eMondrian service in docker-compose.yml:
    extra_hosts:
      - "host.docker.internal:host-gateway"

7.2 Describe your first cube

Example: a ClickHouse table sales with columns sale_date, region, product, quantity, amount.

Create schema/MySales.xml:

<?xml version="1.0" encoding="UTF-8"?>
<Schema name="MySales">
 
  <!-- Dimension table: one row per region -->
  <View alias="dim_region">
    <SQL dialect="clickhouse"><![CDATA[
      SELECT region
      FROM sales
      GROUP BY region
    ]]></SQL>
    <!-- Fallback for other databases -->
    <SQL dialect="generic"><![CDATA[
      SELECT region
      FROM sales
      GROUP BY region
    ]]></SQL>
  </View>
 
  <Cube name="Sales" cache="true" enabled="true">
 
    <!-- Fact rows -->
    <View alias="fact">
      <SQL dialect="clickhouse"><![CDATA[
        SELECT region, quantity, amount
        FROM sales
      ]]></SQL>
      <SQL dialect="generic"><![CDATA[
        SELECT region, quantity, amount
        FROM sales
      ]]></SQL>
    </View>
 
    <Dimension name="Region" foreignKey="region"
               table="dim_region" primaryKey="region">
 
      <!-- AttributeMapping must come before DimensionAttribute / Hierarchy -->
      <AttributeMapping attribute="Region" factColumn="region"/>
 
      <DimensionAttribute name="Region" usage="Key">
        <KeyColumn columnName="region" dataType="String"/>
      </DimensionAttribute>
 
      <Hierarchy hasAll="true" allMemberName="All Regions">
        <Level name="Region" uniqueMembers="true" sourceAttribute="Region"/>
      </Hierarchy>
    </Dimension>
 
    <Measure name="Amount"   column="amount"   aggregator="sum" formatString="#,##0.00"/>
    <Measure name="Quantity" column="quantity" aggregator="sum" formatString="#,###"/>
 
    <CalculatedMember name="Avg Price" dimension="Measures" formatString="#,##0.00">
      <Formula>[Measures].[Amount] / [Measures].[Quantity]</Formula>
    </CalculatedMember>
 
  </Cube>
</Schema>

Tips:

  • Element order is significant inside a <Dimension>: AttributeMapping → DimensionAttribute → Hierarchy.
  • Use AttributeMapping only when the dimension key is unique in the dimension view. If a key appears twice (e.g. two spellings of a city name), the join fans out and totals silently change. Fix the view first — see the comment on Origin Airport in schema/OnTime.xml.
  • schema/OnTime.xml is a complete, larger example: time hierarchy (Year → Quarter → Month), several dimensions, distinct count, calculated measures. schema/Foodmart.xml includes an example role that restricts access to a cube.
  • Give every <View> a generic SQL variant next to the database-specific one. eMondrian picks the variant for the running database and falls back to generic; without a fallback the same schema fails on another database.
  • Use dataType on <KeyColumn> (not type — it’s silently ignored) and mark the key attribute with usage="Key".
  • Check your schema with the validate_schema MCP tool (section 6) — it reports problems the engine ignores silently, such as misspelled attributes.
  • You can also build and edit schemas in the browser: http://localhost/schema-editor/. The Catalog Editor at http://localhost/catalog-editor/ edits datasources.xml the same way.

Or let an AI agent write the schema

With MCP connected (section 6), an agent can draft, validate and save the schema for you. It uses the built-in cube-authoring guide (get_cube_authoring_guide), checks the result (validate_schema) and writes it to the catalog (save_schema).

  1. Add the catalog to datasources.xml as in 7.1, create a starting schema file (for example, the one above), and restart.

  2. Ask your agent, for example:

    “In catalog MySales, create a cube Sales on the ClickHouse table sales (columns: sale_date, region, product, quantity, amount). Add a Time dimension (Year → Month) from sale_date, Region and Product dimensions, measures Amount and Quantity, and a calculated measure Avg Price = Amount / Quantity. Follow the cube authoring guide, validate the schema, then save it.”

  3. Restart to load the saved schema: docker compose restart eMondrian.

  4. Ask the agent to check the result: “Show total Amount by Region for the last year.”

Review what the agent wrote before you rely on it — especially dimension keys: they must be unique (see the tips above). The schema is a plain XML file in schema/, so you can read, diff and version it like code.

7.3 Apply the changes

docker compose restart eMondrian

Then open the OLAP Client at http://localhost/client/, choose catalog MySales, type this query into the MDX editor and click Run:

SELECT {[Measures].[Amount], [Measures].[Avg Price]} ON COLUMNS,
       [Region].[Region].Members ON ROWS
FROM [Sales]

Connect Excel or Power BI exactly as in steps 4–5 — select the MySales database.

Caching

Excel and Power BI keep a session open with eMondrian. Within a session, repeated queries are answered from eMondrian’s cache without new SQL. After loading new data into your database or changing a schema file, restart (docker compose restart eMondrian) to clear the cache. Caching is on by default — there is nothing to configure.

7.4 PostgreSQL

The PostgreSQL driver is included. Add a catalog:

<Catalog name="MyPostgres">
  <DataSourceInfo>Provider=mondrian;Jdbc=jdbc:postgresql://host.docker.internal:5432/mydb;JdbcUser=myuser;JdbcPassword=mypassword;JdbcDrivers=org.postgresql.Driver</DataSourceInfo>
  <Definition>/WEB-INF/schema/MyPostgres.xml</Definition>
</Catalog>

In the schema, use dialect="postgres" (not postgresql) for PostgreSQL-specific SQL, plus a generic variant.

7.5 Other databases: add a JDBC driver

For MySQL and other databases, put the driver JAR into the container’s WEB-INF/lib:

  1. Download the driver JAR, e.g. mysql-connector-j-9.1.0.jar, into a drivers/ folder in the project.
  2. Mount it in docker-compose.yml under the eMondrian service volumes: (there is a commented-out example for ClickHouse in the file):
    - ./drivers/mysql-connector-j-9.1.0.jar:/usr/local/tomcat/webapps/emondrian/WEB-INF/lib/mysql-connector-j-9.1.0.jar
  3. Use the driver class in datasources.xml (JdbcDrivers=com.mysql.cj.jdbc.Driver).
  4. Recreate the container: docker compose up -d.

Don’t put drivers into modules/ — that folder is for eMondrian modules, not for JDBC drivers.


8. Troubleshooting

ProblemWhat to check
Setup stops: port 80 in useAnother web server (IIS, Apache, nginx) runs on port 80. Set EMONDRIAN_PORT in .env and run the script again.
Linux: permission denied on DockerYour user was just added to the docker group. Log out and in, or run newgrp docker.
Windows: setup stops after installing WSLRestart Windows, then run the setup script again.
My catalog doesn’t appear<DataSourceInfo> must be before <Definition>. & must be &amp;. Did you restart (docker compose restart eMondrian)?
Cube missing or schema errorOpen http://localhost/logs/ → mondrian.log. The error names the element that failed. Check element order inside <Dimension>.
Can’t reach my databaseFrom the container, localhost isn’t your machine — use host.docker.internal (on Linux add extra_hosts, see 7.1). Check firewall and DB credentials.
New data doesn’t show upeMondrian caches results within a client session. Restart (docker compose restart eMondrian) or reconnect the client.
Wrong totalsCheck that dimension keys are unique in the dimension view (see 7.2). mondrian-sql.log shows the SQL eMondrian sends.
Excel can’t connectOpen http://localhost/xmla in a browser to check the server responds. Use the port from .env if you changed it.
Power BI: error when connecting or refreshing, or no fieldsIs the evaluation key activated on http://localhost, and not expired? Excel keeps working without a key — if Excel works and Power BI doesn’t, check the key first.
No .lic files foundNo key is activated. Activate one (5.1) — it takes effect without a restart.
License has expiredRequest an extension or a commercial license, activate it, then docker compose restart eMondrian.
MCP client can’t connectOpen http://localhost to check the server is up. The URL must end in /emondrian/mcp/sse and use the port from .env if you changed it. The client must support the SSE transport.
MCP: Error POSTing to endpoint (HTTP 404)The /emondrian prefix is missing from the URL, or an older module is installed — update Community (git pull, docker compose up -d).
MCP: Module 'MCP' not found in license modulesYour key was issued for DAX only (evaluation keys issued before 30 September 2026). Request a new evaluation key — it covers DAX and MCP. If another key was already active, run docker compose restart eMondrian after activating.
MCP: DAX query failsName the cube if the catalog has several (FoodMart: six). Write measures table-qualified: 'HR'[Org Salary] — unqualified measure references are a known open issue.
Agent’s answer looks wrongAsk the agent to show the MDX it ran, and run it in the OLAP Client. Check the schema — the agent uses the measure definitions it finds there.
A DAX query failsCopy it from Performance analyzer and open an issue — failing queries are how compatibility improves.

Logs on disk: ./logs/ in the project folder — mondrian.log, mondrian-sql.log, mondrian-mdx.log, plus dated older files (written by the container as root; deleting them needs sudo).


9. Stop, start, reset

docker compose stop          # stop, keep everything
docker compose up -d         # start again
docker compose down          # remove containers, keep the loaded data
docker compose down -v       # remove containers and the ClickHouse data

Next steps