o2-readonly
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@o2-readonlyshow me the schema for the api_error stream"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
mcp-openobserve-readonly
A read-only MCP server for OpenObserve.
It lets an AI assistant list your log streams, inspect their fields and run SELECT queries against
them — and nothing else.
One file, no dependencies, stdio transport. Node 18 or newer.
you ──▶ assistant ──▶ o2-readonly (this server) ──▶ OpenObserve HTTP API
│
└── only 3 endpoints, SELECT-only SQL, capped rows and time windowWhy it exists
Handing an assistant a generic HTTP tool and your OpenObserve credential means it can call any endpoint the credential allows, including ones that change things. This server sits in between and refuses everything except three read paths, so an assistant investigating an incident can explore logs freely without you worrying about what else it might reach.
Related MCP server: safe-sql-mcp
Tools
Tool | What it does |
| Lists streams with type, document count and last event time. Filter by name substring or stream type; up to 500 results. |
| Field names and types for one stream. |
| Runs a single |
o2_search parameters
Name | Default | Notes |
| required | One |
|
| How far back to look from |
|
| ISO-8601. |
|
| Rows to return, maximum 200. |
|
|
|
// list the streams whose name contains "api"
{ "name": "o2_list_streams", "arguments": { "filter": "api" } }
// errors in the last hour
{ "name": "o2_search", "arguments": {
"sql": "SELECT _timestamp, level, message FROM \"my_stream\" WHERE level = 'error' ORDER BY _timestamp DESC",
"minutes": 60, "size": 100 } }
// a specific window, hours grouped
{ "name": "o2_search", "arguments": {
"sql": "SELECT histogram(_timestamp, '1 hour') AS hr, count(*) AS n FROM \"my_stream\" GROUP BY hr ORDER BY hr",
"start": "2026-03-26T00:00:00Z", "end": "2026-03-27T00:00:00Z" } }What it refuses
Enforced inside the process, whatever the credential is allowed to do:
Three endpoints only —
GET /api/{org}/streams,GET /api/{org}/streams/{stream}/schema,POST /api/{org}/_search. The onlyPOSTis the search itself. Paths that change under URL normalisation are rejected.SELECT/WITHonly — one statement, no semicolons, no SQL comments, unbalanced quotes rejected, and a keyword deny-list (insert,update,delete,drop,alter,create,truncate,grant,revoke,merge,copy,attach,detach,exec,execute) outside string literals. The search API can't write anyway; this is a second line of defence.Caps — 200 rows, 500 characters per cell, 60,000 characters of output, and a time window of
O2_MAX_WINDOW_MINminutes (1440 by default). Oversized results are halved until they fit and markedtruncated.Stream names must match
[A-Za-z0-9_][A-Za-z0-9_.-]*, and the organisation name[A-Za-z0-9_-]+.
It does not weaken the credential itself. These limits live in this process. If someone runs a different client with the same credential, they get whatever that credential allows. For a real guarantee, put a non-admin, read-only OpenObserve user in
O2_AUTH— see SETUP.md.
Configuration
Variable | Default | Meaning |
| — | Required. |
|
| Your OpenObserve base URL. |
|
| Organisation name. |
|
| Largest allowed query window, in minutes. |
Quick start
git clone https://github.com/KietDev-JS/mcp-openobserve-readonly.git
cd mcp-openobserve-readonly
# Claude Code
claude mcp add o2-readonly \
-e O2_BASE_URL="https://openobserve.example.com" \
-e O2_AUTH="Basic $(printf 'you@example.com:password' | base64)" \
-- node "$PWD/server.mjs"
claude mcp list # expect: o2-readonly … ✔ ConnectedFull walkthrough, including Claude Desktop and other MCP clients, credential setup and troubleshooting: SETUP.md.
Notes and limits
A query window covers at most 24 hours by default. To look further back, query one day at a time with explicit
startandend, or raiseO2_MAX_WINDOW_MIN.histogram(_timestamp, '1 hour')is the practical way to see the shape of a log volume over time.Timestamps are microseconds. Results add a readable
_timefield alongside_timestamp.The server speaks MCP protocol versions
2025-11-25,2025-06-18,2025-03-26and2024-11-05, and echoes back whichever the client asks for if it recognises it.
License
MIT.
This server cannot be deployed
Maintenance
Related MCP Connectors
Safe, read-only Postgres and MySQL access for AI agents. Audit log + column-level controls.
Query 40 databases from Claude, ChatGPT, or Cursor — on any device. Read-only, encrypted, audited.
Query your org's data in natural language — read-only MCP access to SQL, NoSQL, files & warehouses.
Query your warehouse or a CSV with Claude/ChatGPT over MCP, governed by table-level ACL + audit.
Related MCP Servers
- AlicenseAqualityAmaintenanceAllows AI assistants to list tables, read data, and execute SQL queries through a controlled interface, making database exploration and analysis safer and more structured.33,443 PyPI1,394MIT
- FlicenseNot gradedqualityDmaintenanceEnables read-only SQL database access for AI assistants, allowing schema exploration and safe query execution without risk of data modification.-
- FlicenseNot gradedqualityDmaintenanceEnables AI assistants to query SQL databases safely with read-only access, allowing schema discovery and SELECT queries while blocking writes and DDL operations.-
- AlicenseNot gradedqualityCmaintenanceEnables an AI assistant to run guarded, read-only SQL queries against a Postgres database with enforced limits and validation.MIT