| title | Wavelet MCP server for always-on agents |
|---|---|
| sidebarTitle | MCP (always-on agents) |
| description | Expose Wavelet queries and events to always-on AI agents via Model Context Protocol. Agents can query real-time data, emit events, and run SQL, no HTTP client needed. |
Wavelet includes an MCP (Model Context Protocol) server that lets always-on AI agents interact with your queries and events using natural language tool calls. Agents can query computed results, write events, and run read-only SQL.
npm install @risingwave/wavelet-mcpAdd to your project's .mcp.json:
{
"mcpServers": {
"wavelet": {
"command": "npx",
"args": ["wavelet-mcp"],
"env": {
"WAVELET_DATABASE_URL": "postgresql://root@localhost:4566/dev"
}
}
}
}Add to claude_desktop_config.json:
{
"mcpServers": {
"wavelet": {
"command": "npx",
"args": ["wavelet-mcp"],
"env": {
"WAVELET_DATABASE_URL": "postgresql://root@localhost:4566/dev"
}
}
}
}Add to .cursor/mcp.json:
{
"mcpServers": {
"wavelet": {
"command": "npx",
"args": ["wavelet-mcp"],
"env": {
"WAVELET_DATABASE_URL": "postgresql://root@localhost:4566/dev"
}
}
}
}| Variable | Default | Description |
|---|---|---|
WAVELET_DATABASE_URL |
postgresql://root@localhost:4566/dev |
RisingWave connection string |
The MCP server auto-discovers queries and events from RisingWave catalogs and exposes six tools:
List all materialized views with their column schemas.
Agent: "What queries are available?"
→ list_queries()
→ { "leaderboard": { "columns": [{ "name": "player_id", "type": "varchar" }, ...] } }
Query a materialized view with optional filtering.
| Parameter | Type | Required | Description |
|---|---|---|---|
query |
string |
Yes | Query name |
filter |
object |
No | Key-value pairs for WHERE clause |
limit |
number |
No | Max rows (default: 100) |
Agent: "Show me Alice's leaderboard entry"
→ query({ query: "leaderboard", filter: { player_id: "alice" } })
→ { "query": "leaderboard", "rows": [{ "player_id": "alice", "total_score": 350 }], "count": 1 }
List all event definitions with their column schemas.
Agent: "What events can I write to?"
→ list_events()
→ { "game_events": { "columns": [{ "name": "player_id", "type": "varchar" }, ...] } }
Write a single event.
| Parameter | Type | Required | Description |
|---|---|---|---|
event |
string |
Yes | Event name |
data |
object |
Yes | Event data (column-value pairs) |
Agent: "Record a win for Alice with score 100"
→ emit_event({ event: "game_events", data: { player_id: "alice", action: "win", score: 100 } })
→ { "ok": true, "event": "game_events", "columns": ["player_id", "action", "score"] }
Write multiple events at once.
| Parameter | Type | Required | Description |
|---|---|---|---|
event |
string |
Yes | Event name |
events |
object[] |
Yes | Array of event objects |
Agent: "Record 3 game results"
→ emit_batch({ event: "game_events", events: [
{ player_id: "alice", action: "win", score: 100 },
{ player_id: "bob", action: "loss", score: -50 },
{ player_id: "charlie", action: "win", score: 75 }
]})
→ { "ok": true, "event": "game_events", "count": 3 }
Execute a read-only SQL query against RisingWave.
| Parameter | Type | Required | Description |
|---|---|---|---|
sql |
string |
Yes | SQL query (must start with SELECT) |
Agent: "What's the average score per action type?"
→ run_sql({ sql: "SELECT action, AVG(score) as avg_score FROM game_events GROUP BY action" })
→ { "rows": [{ "action": "win", "avg_score": 87.5 }, ...], "count": 2 }
An AI agent periodically checks tenant_usage to detect anomalies:
Agent: "Check if any tenant has spent more than $100 today"
→ query({ query: "tenant_usage", filter: {} })
→ Finds tenant with $142 spend, alerts the user
An agent writes events and reads results to make decisions:
Agent: "Add a game event and check the new leaderboard"
→ emit_event({ event: "game_events", data: { player_id: "alice", action: "win", score: 200 } })
→ query({ query: "leaderboard" })
→ "Alice is now #1 with 550 points"
An agent explores the data schema and runs ad-hoc queries:
Agent: "What data is available?"
→ list_queries() -- sees leaderboard, model_stats
→ list_events() -- sees game_events, llm_events
→ run_sql({ sql: "SELECT COUNT(*) FROM game_events" })
→ "There are 1,247 game events across 2 queries and 2 events"