Command Palette

Search for a command to run...

UnylyUnyly
Browse all

Cassandra Mcp Server Free

FreeNot checked

Cassandra MCP server — free cloud Apache Cassandra with CQL for Claude, ChatGPT and AI agents

GitHubEmbed

About

Cassandra MCP server — free cloud Apache Cassandra with CQL for Claude, ChatGPT and AI agents

README

Cassandra CQL MCP License: MIT

The query that doesn't work

Someone models a warehouse sensor feed. One table, readings, primary key (sensor_id, reading_time). It's clean, it ingests beautifully, and then the first real question arrives: which sensors in Aisle 4 went above 8°C last Tuesday?

InvalidRequest: Error from server: code=2200 [Invalid query]
  message="Cannot execute this query as it might involve data filtering and thus
  may have unpredictable performance. If you want to execute this query despite
  the performance unpredictability, use ALLOW FILTERING"

Someone appends ALLOW FILTERING, the query returns, everyone moves on, and eighteen months later that query is a coordinator-node incident.

Cassandra isn't being difficult. It's telling you that you designed the table before you knew the questions, which is backwards from every relational habit you have. You don't normalise and then query. You enumerate the queries, then write one table per query, and you accept that the same reading will be stored three times.

That inversion takes practice, and practice needs a live ring — which historically meant Docker, three nodes, a gossip config and an afternoon. This repo skips that: a free Cassandra 4.1.4 instance reachable from your MCP client, so you can model, load, query and get it wrong somewhere cheap.

What's here

examples/
  schema.cql          keyspace + three tables for three access patterns
  rollups.cql         the queries each table exists to serve, and one that fails
  ingest_readings.py  Python — writes a day of sensor data through MCP
  README.md

The connection in these files is called sensors, so the tools are sensors_query, sensors_store, sensors_list_tables and sensors_annotate_table. Yours will be named after whatever you call the connection in the dashboard.

Partition keys in one page

A CQL primary key has two parts and they do completely different jobs.

PRIMARY KEY ( (warehouse_id, day) , sensor_id, reading_time )
              └── partition key ──┘  └─ clustering columns ─┘
                  which machine          sort order inside
                  holds the rows          that partition

Rules that follow from that, none of which are negotiable:

  1. Every query must supply the full partition key. Cassandra hashes it to find the node. No partition key, no idea where to look, hence the error above.
  2. Clustering columns are queryable in order, left to right, and only as a prefix. With clustering (sensor_id, reading_time) you can filter on sensor_id, or on sensor_id and reading_time. You cannot filter on reading_time alone.
  3. Partitions should be bounded. A partition key of just warehouse_id means one partition grows forever. Adding day — a bucket — caps it. This is the single most common modelling fix.
  4. There are no joins. If two questions need the same row shaped two ways, write it twice. Disk is cheaper than a coordinator fan-out.

Point 3 has a corollary people miss: bucketing changes your read pattern too. Querying a week now means seven partition reads, which you issue as seven concurrent statements rather than one range scan. Both halves of that trade are easier to believe once you have run them against a real keyspace.

The dataset

A cold-chain warehouse. Sensors on shelving units report temperature, humidity and battery level every few minutes. Three questions the operations team actually asks:

# Question Table Partition key Clustering
1 What has sensor S been reporting today? readings_by_sensor (sensor_id, day) reading_time DESC
2 What breached threshold in aisle A this week? alerts_by_aisle (warehouse_id, aisle, day) raised_at DESC, sensor_id
3 Which sensors have a dying battery? sensor_health (warehouse_id) battery_pct ASC, sensor_id

Same underlying events, three tables, and the write path fans out to all three. That's the trade Cassandra asks for: more writes, more storage, in exchange for every read being a single-partition lookup with a known cost.

sensor_health gets away with an unbucketed partition key because it holds one row per sensor, not one per reading — bounded by the size of the warehouse, not by time.

The CQL for all three tables is in examples/schema.cql, ready to paste into a Cassandra session and take apart.

Getting connected

Sign up at freebase.cloud, start a session on the Cassandra engine, then go to Settings → MCP, issue a New Token against that connection, and take the URL it gives you.

claude mcp add --transport http sensors https://freebase.cloud/api/mcp/YOUR_TOKEN

The token is carried in the URL path, so there's no header configuration anywhere. Same URL, in each client's own dialect:

// Claude Code .mcp.json — "type" is mandatory here
{ "mcpServers": { "sensors": { "type": "http", "url": "https://freebase.cloud/api/mcp/YOUR_TOKEN" } } }
// Zed settings.json
{ "context_servers": { "sensors": { "url": "https://freebase.cloud/api/mcp/YOUR_TOKEN" } } }
// Cline — the value is camelCase, unlike every other client
{ "mcpServers": { "sensors": { "type": "streamableHttp", "url": "https://freebase.cloud/api/mcp/YOUR_TOKEN", "disabled": false, "autoApprove": [] } } }

Roo Code wants the same thing kebab-cased ("type": "streamable-http") in .roo/mcp.json. Claude Desktop, Claude web and Cowork take the URL through Settings → Connectors → Add custom connector — there is no file to edit, and claude_desktop_config.json cannot hold a remote HTTP server no matter what an older tutorial says. The Claude connection walkthrough has screenshots of that dialog if you want to check yours against it.

For an n8n workflow, use the MCP Client Tool node (n8n 1.104.0+) with Server Transport set to HTTP Streamable and Authentication set to None. The docs page for that node still shows only the legacy SSE field; the node itself has the dropdown.

The tools

Tool Arguments Behaviour
sensors_query query A CQL statement. Read path.
sensors_store table, rows[], mode Rows as JSON objects; append or replace
sensors_list_tables Tables, row counts, columns, saved annotations
sensors_annotate_table table, description, format Persisted schema notes

Access is over the hosted HTTP query API and over MCP. Port 9042 and cqlsh are named throughout this README because they define the dialect you're writing — CQL 3.4 as documented for Cassandra 4.1 — not because there's a raw socket to point a driver at.

Letting the model design the table

This is where an MCP connection earns its place. The useful prompt isn't "insert this row", it's:

I need to answer: for a given aisle, show every temperature breach in the last seven days, newest first. Sensors report every two minutes and there are about 300 of them per aisle. Propose a CQL table and explain the partition sizing.

A model with sensors_list_tables can see what already exists, propose PRIMARY KEY ((warehouse_id, aisle, day), raised_at, sensor_id), and — if you ask it to show its arithmetic — estimate the partition: 300 sensors × 720 readings a day is 216,000 rows before you filter down to breaches, which is comfortable, whereas dropping day from the key would give you 78 million rows a year in a single partition and a node that hates you.

Then you have it run sensors_query with the CREATE TABLE against a throwaway keyspace, load a sample through sensors_store, and ask the real question. The loop from "idea" to "wrong, and here's why" is about ninety seconds.

Annotations stop the guessing

sensors_annotate_table writes a description that persists on the connection and is read back when the model reconnects. For Cassandra the field that matters most is the one describing the key, because nothing in a row listing tells the model why a query needs day in the WHERE clause.

{
  "table": "alerts_by_aisle",
  "description": "One row per threshold breach. Denormalised from readings_by_sensor — do not treat it as the source of truth for raw readings. Every query MUST supply warehouse_id, aisle and day; day is a yyyy-mm-dd bucket added to bound partition growth. Querying a week means seven statements, not a range scan. Never add ALLOW FILTERING to work around a missing key.",
  "format": {
    "structure": "PRIMARY KEY ((warehouse_id, aisle, day), raised_at, sensor_id) WITH CLUSTERING ORDER BY (raised_at DESC)",
    "ttl": "rows written with TTL 7776000 (90 days)"
  }
}

That last sentence in the description is worth more than any amount of prompt engineering. Models reach for ALLOW FILTERING because it makes the error go away, and an annotation is the only place to tell them not to that survives a new conversation.

Things CQL will not do for you

Be honest about the shape of the tool:

  • No joins, no subqueries. Denormalise, or do the join in the application.
  • No GROUP BY across partitions. Aggregates are single-partition. Rollups are a write-time concern — counters, or a summary table you maintain yourself.
  • No arbitrary ORDER BY. Order is baked into CLUSTERING ORDER BY at table creation. You can reverse it at query time; you cannot sort by an unclustered column.
  • IN on a partition key looks fine and isn't. A large IN list makes the coordinator fan out to every replica involved and wait for the slowest. Concurrent single-partition queries beat it.
  • Secondary indexes are a trap at scale. They work, they're occasionally right for a low-cardinality column inside a known partition, and they are not a substitute for a table.

What does work, and is worth using: collections (list, set, map), user-defined types, tuples, per-row and per-column TTL, lightweight transactions via IF NOT EXISTS / IF conditions, batches within a keyspace, and tunable consistency per statement — all of it present on the Cassandra 4.1 build described here.

Limits worth stating

The free tier suits development, prototyping and small production workloads. This is a place to learn partition modelling and run a real schema, not a place to benchmark a ring — there's one endpoint, so consistency-level tuning is something you write and reason about rather than something you can measure the failure modes of. No SLA, uptime figure or backup schedule is claimed here because none is published.

An MCP client with sensors_store can write and can drop tables. The token is the access boundary; treat it as a credential, and revoke it from Settings → MCP on the connection that issued it when you are done.

Reading list


Released under MIT. freebase.cloud is an independent service and is not affiliated with the Apache Software Foundation, DataStax, Anthropic, or n8n.

from github.com/freebase-cloud/cassandra-mcp-server-free

Installing Cassandra Mcp Server Free

This server has no published package — it is built from source. Open the repository and follow its README.

▸ github.com/freebase-cloud/cassandra-mcp-server-free

FAQ

Is Cassandra Mcp Server Free MCP free?

Yes, Cassandra Mcp Server Free MCP is free — one-click install via Unyly at no cost.

Does Cassandra Mcp Server Free need an API key?

No, Cassandra Mcp Server Free runs without API keys or environment variables.

Is Cassandra Mcp Server Free hosted or self-hosted?

Self-hosted: the server runs locally on your machine via the install command above.

How do I install Cassandra Mcp Server Free in Claude Desktop, Claude Code or Cursor?

Open Cassandra Mcp Server Free on unyly.org, pick your client tab (Claude Desktop, Claude Code, Cursor) and press Install — the config is generated automatically, no JSON editing.

Related MCPs

Compare Cassandra Mcp Server Free with

Not sure what to pick?

Find your stack in 60 seconds

Author?

Embed badge for your README

Browse similar

All data MCPs