queryglot 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. queryglot-0.1.0/LICENSE +21 -0
  2. queryglot-0.1.0/PKG-INFO +206 -0
  3. queryglot-0.1.0/README.md +182 -0
  4. queryglot-0.1.0/pyproject.toml +49 -0
  5. queryglot-0.1.0/src/queryglot/__init__.py +30 -0
  6. queryglot-0.1.0/src/queryglot/_static/.gitkeep +0 -0
  7. queryglot-0.1.0/src/queryglot/_static/assets/index-1lL6zxyT.js +9 -0
  8. queryglot-0.1.0/src/queryglot/_static/assets/index-8ImQIHea.js +9 -0
  9. queryglot-0.1.0/src/queryglot/_static/assets/index-BDeUwW1r.js +9 -0
  10. queryglot-0.1.0/src/queryglot/_static/assets/index-B_o_39XA.css +1 -0
  11. queryglot-0.1.0/src/queryglot/_static/assets/index-Bsk8qv60.js +9 -0
  12. queryglot-0.1.0/src/queryglot/_static/assets/index-BzbhFHkF.js +9 -0
  13. queryglot-0.1.0/src/queryglot/_static/assets/index-CQP-25bj.css +1 -0
  14. queryglot-0.1.0/src/queryglot/_static/assets/index-CV0K9dRj.css +1 -0
  15. queryglot-0.1.0/src/queryglot/_static/assets/index-CZbVKFtk.js +9 -0
  16. queryglot-0.1.0/src/queryglot/_static/assets/index-CtT8lmCb.js +9 -0
  17. queryglot-0.1.0/src/queryglot/_static/assets/index-D1uIJgrL.css +1 -0
  18. queryglot-0.1.0/src/queryglot/_static/assets/index-D9tF5GUl.js +9 -0
  19. queryglot-0.1.0/src/queryglot/_static/assets/index-DFNjME17.js +9 -0
  20. queryglot-0.1.0/src/queryglot/_static/assets/index-JkbG_W0h.css +1 -0
  21. queryglot-0.1.0/src/queryglot/_static/assets/index-L6MxI3WS.js +9 -0
  22. queryglot-0.1.0/src/queryglot/_static/assets/index-Uuctas8m.js +9 -0
  23. queryglot-0.1.0/src/queryglot/_static/assets/index-VxpsF3Fj.css +1 -0
  24. queryglot-0.1.0/src/queryglot/_static/assets/index-Xh50kjFZ.js +9 -0
  25. queryglot-0.1.0/src/queryglot/_static/assets/index-ZOPLw8dP.js +9 -0
  26. queryglot-0.1.0/src/queryglot/_static/assets/index-qzRFxYgo.js +9 -0
  27. queryglot-0.1.0/src/queryglot/_static/favicon.svg +1 -0
  28. queryglot-0.1.0/src/queryglot/_static/index.html +14 -0
  29. queryglot-0.1.0/src/queryglot/_static/widget.js +1 -0
  30. queryglot-0.1.0/src/queryglot/backends/__init__.py +41 -0
  31. queryglot-0.1.0/src/queryglot/backends/elastic.py +103 -0
  32. queryglot-0.1.0/src/queryglot/backends/http.py +46 -0
  33. queryglot-0.1.0/src/queryglot/backends/openapi.py +237 -0
  34. queryglot-0.1.0/src/queryglot/backends/prometheus.py +318 -0
  35. queryglot-0.1.0/src/queryglot/catalog.py +54 -0
  36. queryglot-0.1.0/src/queryglot/cli.py +59 -0
  37. queryglot-0.1.0/src/queryglot/dataset.py +266 -0
  38. queryglot-0.1.0/src/queryglot/engine.py +119 -0
  39. queryglot-0.1.0/src/queryglot/graph.py +162 -0
  40. queryglot-0.1.0/src/queryglot/llm.py +98 -0
  41. queryglot-0.1.0/src/queryglot/mcp_server.py +88 -0
  42. queryglot-0.1.0/src/queryglot/prompts.py +64 -0
  43. queryglot-0.1.0/src/queryglot/rerank.py +70 -0
  44. queryglot-0.1.0/src/queryglot/retrieve.py +115 -0
  45. queryglot-0.1.0/src/queryglot/server.py +340 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Divyanshu Sharma
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,206 @@
1
+ Metadata-Version: 2.3
2
+ Name: queryglot
3
+ Version: 0.1.0
4
+ Summary: One question, many query languages. Schema-aware natural-language search over your observability stack, as an MCP server.
5
+ License: MIT
6
+ Keywords: mcp,prometheus,elasticsearch,promql,observability,rag,llm
7
+ Author: Divyanshu Sharma
8
+ Author-email: sharmadivyanshu24@gmail.com
9
+ Requires-Python: >=3.11,<4.0
10
+ Classifier: License :: OSI Approved :: MIT License
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3.11
13
+ Classifier: Programming Language :: Python :: 3.12
14
+ Classifier: Programming Language :: Python :: 3.13
15
+ Provides-Extra: serve
16
+ Requires-Dist: fastapi (>=0.115,<0.116) ; extra == "serve"
17
+ Requires-Dist: langgraph (>=1.2,<2.0)
18
+ Requires-Dist: mcp (>=1.0,<2.0)
19
+ Requires-Dist: pydantic (>=2.9,<3.0)
20
+ Requires-Dist: uvicorn (>=0.32,<0.33) ; extra == "serve"
21
+ Project-URL: Repository, https://github.com/sharmadivyanshu/queryglot
22
+ Description-Content-Type: text/markdown
23
+
24
+ # queryglot
25
+
26
+ **One question, many query languages.** Schema-aware natural-language search
27
+ over your observability stack — Prometheus, Elasticsearch — and any
28
+ OpenAPI-described API, shipped as an MCP server any agent can plug into.
29
+
30
+ > "p95 latency by route" is easy. Knowing YOUR latency metric is called
31
+ > `http_server_request_duration_seconds` and carries a `route` label — that's
32
+ > the actual problem. Frontier models write fluent PromQL over metric names
33
+ > that don't exist.
34
+
35
+ ## How it works
36
+
37
+ ```
38
+ question ──> retrieve ──> compile ──> validate ──> execute
39
+ (BM25 + synonyms (LLM, schema (the backend's OWN (real data,
40
+ over YOUR schema, slice in the parser + unknown- query shown)
41
+ introspected live) prompt) metric check)
42
+ │ ▲ │ parse error
43
+ │ nothing matches └─── bounded repair ┘
44
+
45
+ ABSTAIN — refuses to guess a metric name
46
+ ```
47
+
48
+ - **Retrieval owns facts** (your metric names, labels, index fields —
49
+ introspected from the live backend, never hallucinated). An LLM reranker
50
+ orders the candidates by intent — over a closed set it can never add to.
51
+ - **The model owns syntax** (PromQL / Query DSL — swap in your own fine-tune
52
+ via any OpenAI-compatible endpoint, including `mlx_lm.server` on a Mac).
53
+ - **The backend owns truth**: every query is validated by the server's own
54
+ parser (`format_query`, `_validate/query`) before execution, and parse
55
+ errors drive a bounded repair loop.
56
+ - **Abstention is a feature**: off-schema questions get a refusal, not an
57
+ invented metric. The eval scores this.
58
+
59
+ ## Use it from any MCP client
60
+
61
+ ```json
62
+ {
63
+ "mcpServers": {
64
+ "queryglot": {
65
+ "command": "queryglot-mcp",
66
+ "env": {
67
+ "QUERYGLOT_PROMETHEUS": "http://localhost:9090",
68
+ "QUERYGLOT_ELASTIC": "http://localhost:9200",
69
+ "QUERYGLOT_OPENAPI": "http://localhost:8081/api/v3",
70
+ "QUERYGLOT_LLM_URL": "http://localhost:11434/v1",
71
+ "QUERYGLOT_LLM_MODEL": "qwen3.5:4b"
72
+ }
73
+ }
74
+ }
75
+ }
76
+ ```
77
+
78
+ Tools exposed: `search(question, backend?)`, `list_schema(query?)`,
79
+ `refresh_schema()`.
80
+
81
+ Or the CLI:
82
+
83
+ ```bash
84
+ queryglot "p95 http request duration" --prometheus http://localhost:9090
85
+ ```
86
+
87
+ Or run an HTTP server with the ask-widget and query playground:
88
+
89
+ ```bash
90
+ pip install "queryglot[serve]" # or: poetry install --extras serve
91
+ queryglot-serve --prometheus http://localhost:9090
92
+ ```
93
+
94
+ `queryglot-serve` also serves the query playground at `/` and the embeddable
95
+ ask-widget bundle at `/widget.js` — see "Embed the ask-widget" below.
96
+
97
+ The playground is a small Discover-style console: your schema in a filterable
98
+ rail (type badges, prefix groups, and the items the last answer actually
99
+ used), a time-range picker whose window runs as a real `query_range` — the
100
+ window comes from the picker, never the model, so the compile prompt stays
101
+ byte-stable — and results as a bar chart or histogram with the raw rows one
102
+ toggle away. Answered questions also get a one-sentence conversational
103
+ summary, grounded strictly on the returned data (never computed, never
104
+ invented — an empty summary beats a wrong one), and repeat questions are
105
+ served from a short answer cache with an honest `cached Ns ago` tag and a
106
+ fresh re-run button.
107
+
108
+ Environment variables (serve only):
109
+ - `QUERYGLOT_SERVE_TOKEN` — bearer token for `/api/*` endpoints. Empty = open (intended for localhost/demo).
110
+ - `QUERYGLOT_CORS_ORIGINS` — comma-separated allowed origins for embedding.
111
+
112
+ Any OpenAI-compatible endpoint works as the model: OpenAI, Ollama, or your own
113
+ LoRA behind `mlx_lm.server` — that last one is the point of `finetune/`.
114
+
115
+ ## Embed the ask-widget
116
+
117
+ `queryglot-serve` ships a self-contained widget: a floating "Ask" pill that
118
+ opens a search panel wired to the same schema-grounded engine as the CLI and
119
+ MCP server. Drop one script tag on any page:
120
+
121
+ ```html
122
+ <script
123
+ src="https://your-queryglot-host/widget.js"
124
+ data-api="https://your-queryglot-host"
125
+ data-theme="auto"
126
+ data-token="optional-bearer-token"
127
+ data-backend="optional-backend-name"
128
+ ></script>
129
+ ```
130
+
131
+ - `data-api` (required) — base URL of the queryglot HTTP API.
132
+ - `data-theme` — `light`, `dark`, or `auto` (default; follows the host page's `prefers-color-scheme`).
133
+ - `data-token` — bearer token, only needed when the server sets `QUERYGLOT_SERVE_TOKEN`.
134
+ - `data-backend` — pins searches to one backend instead of auto-routing.
135
+
136
+ See `frontend/README.md` for the build (`npm run build:all`) that packages
137
+ the widget and playground into the Python wheel.
138
+
139
+ ## Evaluation — deterministic, no LLM judge
140
+
141
+ `eval/run_eval.py` scores golden questions against a live backend: the
142
+ outcome must match, required metrics must appear in the query, and the query
143
+ must actually execute. Abstention cases score correct only on refusal.
144
+ `eval/docker-compose.yml` brings up real backends; CI runs the full
145
+ integration suite against a real Prometheus and petstore on every push.
146
+
147
+ ## Status
148
+
149
+ **v0.1.0** — the RAG arm, working end to end.
150
+
151
+ - [x] Prometheus + Elasticsearch backends (introspect / validate / execute)
152
+ - [x] BM25 + synonym schema retrieval, exact-name boosting
153
+ - [x] compile -> validate -> repair -> execute LangGraph with abstention
154
+ - [x] MCP server + CLI; 141 backend tests (live-Prometheus and
155
+ live-petstore integration included, always exercised in CI) plus 82
156
+ frontend tests; CI gates on all of it
157
+ - [x] Verified NL->PromQL dataset generator (parse+execute gated, metric-disjoint splits)
158
+ - [x] Bake-off complete — RAG 8/10, FT-only 3/10, FT+RAG 9/10 on the same
159
+ golden set; full analysis in `finetune/README.md`, build history and
160
+ bugs in `DESIGN_NOTES.md`
161
+ - [x] OpenAPI backend — read-only, GET-only by construction; validated
162
+ against the spec's own contract; petstore-verified in CI
163
+ - [x] HTTP serve layer: answer cache, grounded conversational summaries,
164
+ structured schema API, bearer auth — engine outcomes are always 200
165
+ payloads (an abstention is an answer, not an error)
166
+ - [x] Embeddable ask-widget (~15 KB gz, Shadow-DOM, one script tag) +
167
+ Discover-style playground: schema rail, time-range windows via
168
+ `query_range`, histogram/bar-chart results with rows one toggle away
169
+ - [ ] Loki (LogQL) backend; Datadog connector
170
+
171
+ ## Where this is going: apps that agents can actually use
172
+
173
+ The `Backend` protocol (introspect / validate / execute) is not
174
+ observability-specific. The same loop pointed at a product's own OpenAPI spec
175
+ or database turns any app into something an AI can query *safely*:
176
+
177
+ - **OpenAPI backend — shipped.** Introspects a product's own spec into the
178
+ catalog; questions compile into validated, GET-only API calls. Existing
179
+ OpenAPI->MCP generators dump every endpoint as a tool, which measurably
180
+ degrades agents (arXiv 2411.15399) and executes whatever the model asks.
181
+ queryglot's contribution is the missing layer: schema-grounded retrieval,
182
+ server-side validation, and abstention.
183
+ - **Customer-facing ask widget** — an embeddable search box backed by the
184
+ same engine: visitors' questions become validated queries against the
185
+ app's data, never hallucinated ones.
186
+ - **`llms.txt` + MCP endpoint generation** — one schema catalog, two
187
+ audiences: humans get the widget, agents get a typed, validated interface
188
+ instead of scraping. Discoverability for the agentic web, with execution
189
+ semantics — not just markup.
190
+
191
+ ## Known limits
192
+
193
+ - `metric_candidates` (unknown-metric detection) is regex-based and
194
+ best-effort; the backend parser owns syntax, this only improves error
195
+ messages. Complex PromQL may slip past it — never through the parser.
196
+ - Backend auto-routing is retrieval-strength-based; ambiguous questions
197
+ ("errors in checkout") can route to the wrong store. Pass `backend=` to pin.
198
+ - Synonym table is small and English-only, grown from eval failures.
199
+ - When a backend's catalog is smaller than the retrieval k (8), retrieval
200
+ sends the whole catalog and the abstention gate rarely fires — abstention
201
+ then rests on the validation layer.
202
+
203
+ ## License
204
+
205
+ MIT
206
+
@@ -0,0 +1,182 @@
1
+ # queryglot
2
+
3
+ **One question, many query languages.** Schema-aware natural-language search
4
+ over your observability stack — Prometheus, Elasticsearch — and any
5
+ OpenAPI-described API, shipped as an MCP server any agent can plug into.
6
+
7
+ > "p95 latency by route" is easy. Knowing YOUR latency metric is called
8
+ > `http_server_request_duration_seconds` and carries a `route` label — that's
9
+ > the actual problem. Frontier models write fluent PromQL over metric names
10
+ > that don't exist.
11
+
12
+ ## How it works
13
+
14
+ ```
15
+ question ──> retrieve ──> compile ──> validate ──> execute
16
+ (BM25 + synonyms (LLM, schema (the backend's OWN (real data,
17
+ over YOUR schema, slice in the parser + unknown- query shown)
18
+ introspected live) prompt) metric check)
19
+ │ ▲ │ parse error
20
+ │ nothing matches └─── bounded repair ┘
21
+
22
+ ABSTAIN — refuses to guess a metric name
23
+ ```
24
+
25
+ - **Retrieval owns facts** (your metric names, labels, index fields —
26
+ introspected from the live backend, never hallucinated). An LLM reranker
27
+ orders the candidates by intent — over a closed set it can never add to.
28
+ - **The model owns syntax** (PromQL / Query DSL — swap in your own fine-tune
29
+ via any OpenAI-compatible endpoint, including `mlx_lm.server` on a Mac).
30
+ - **The backend owns truth**: every query is validated by the server's own
31
+ parser (`format_query`, `_validate/query`) before execution, and parse
32
+ errors drive a bounded repair loop.
33
+ - **Abstention is a feature**: off-schema questions get a refusal, not an
34
+ invented metric. The eval scores this.
35
+
36
+ ## Use it from any MCP client
37
+
38
+ ```json
39
+ {
40
+ "mcpServers": {
41
+ "queryglot": {
42
+ "command": "queryglot-mcp",
43
+ "env": {
44
+ "QUERYGLOT_PROMETHEUS": "http://localhost:9090",
45
+ "QUERYGLOT_ELASTIC": "http://localhost:9200",
46
+ "QUERYGLOT_OPENAPI": "http://localhost:8081/api/v3",
47
+ "QUERYGLOT_LLM_URL": "http://localhost:11434/v1",
48
+ "QUERYGLOT_LLM_MODEL": "qwen3.5:4b"
49
+ }
50
+ }
51
+ }
52
+ }
53
+ ```
54
+
55
+ Tools exposed: `search(question, backend?)`, `list_schema(query?)`,
56
+ `refresh_schema()`.
57
+
58
+ Or the CLI:
59
+
60
+ ```bash
61
+ queryglot "p95 http request duration" --prometheus http://localhost:9090
62
+ ```
63
+
64
+ Or run an HTTP server with the ask-widget and query playground:
65
+
66
+ ```bash
67
+ pip install "queryglot[serve]" # or: poetry install --extras serve
68
+ queryglot-serve --prometheus http://localhost:9090
69
+ ```
70
+
71
+ `queryglot-serve` also serves the query playground at `/` and the embeddable
72
+ ask-widget bundle at `/widget.js` — see "Embed the ask-widget" below.
73
+
74
+ The playground is a small Discover-style console: your schema in a filterable
75
+ rail (type badges, prefix groups, and the items the last answer actually
76
+ used), a time-range picker whose window runs as a real `query_range` — the
77
+ window comes from the picker, never the model, so the compile prompt stays
78
+ byte-stable — and results as a bar chart or histogram with the raw rows one
79
+ toggle away. Answered questions also get a one-sentence conversational
80
+ summary, grounded strictly on the returned data (never computed, never
81
+ invented — an empty summary beats a wrong one), and repeat questions are
82
+ served from a short answer cache with an honest `cached Ns ago` tag and a
83
+ fresh re-run button.
84
+
85
+ Environment variables (serve only):
86
+ - `QUERYGLOT_SERVE_TOKEN` — bearer token for `/api/*` endpoints. Empty = open (intended for localhost/demo).
87
+ - `QUERYGLOT_CORS_ORIGINS` — comma-separated allowed origins for embedding.
88
+
89
+ Any OpenAI-compatible endpoint works as the model: OpenAI, Ollama, or your own
90
+ LoRA behind `mlx_lm.server` — that last one is the point of `finetune/`.
91
+
92
+ ## Embed the ask-widget
93
+
94
+ `queryglot-serve` ships a self-contained widget: a floating "Ask" pill that
95
+ opens a search panel wired to the same schema-grounded engine as the CLI and
96
+ MCP server. Drop one script tag on any page:
97
+
98
+ ```html
99
+ <script
100
+ src="https://your-queryglot-host/widget.js"
101
+ data-api="https://your-queryglot-host"
102
+ data-theme="auto"
103
+ data-token="optional-bearer-token"
104
+ data-backend="optional-backend-name"
105
+ ></script>
106
+ ```
107
+
108
+ - `data-api` (required) — base URL of the queryglot HTTP API.
109
+ - `data-theme` — `light`, `dark`, or `auto` (default; follows the host page's `prefers-color-scheme`).
110
+ - `data-token` — bearer token, only needed when the server sets `QUERYGLOT_SERVE_TOKEN`.
111
+ - `data-backend` — pins searches to one backend instead of auto-routing.
112
+
113
+ See `frontend/README.md` for the build (`npm run build:all`) that packages
114
+ the widget and playground into the Python wheel.
115
+
116
+ ## Evaluation — deterministic, no LLM judge
117
+
118
+ `eval/run_eval.py` scores golden questions against a live backend: the
119
+ outcome must match, required metrics must appear in the query, and the query
120
+ must actually execute. Abstention cases score correct only on refusal.
121
+ `eval/docker-compose.yml` brings up real backends; CI runs the full
122
+ integration suite against a real Prometheus and petstore on every push.
123
+
124
+ ## Status
125
+
126
+ **v0.1.0** — the RAG arm, working end to end.
127
+
128
+ - [x] Prometheus + Elasticsearch backends (introspect / validate / execute)
129
+ - [x] BM25 + synonym schema retrieval, exact-name boosting
130
+ - [x] compile -> validate -> repair -> execute LangGraph with abstention
131
+ - [x] MCP server + CLI; 141 backend tests (live-Prometheus and
132
+ live-petstore integration included, always exercised in CI) plus 82
133
+ frontend tests; CI gates on all of it
134
+ - [x] Verified NL->PromQL dataset generator (parse+execute gated, metric-disjoint splits)
135
+ - [x] Bake-off complete — RAG 8/10, FT-only 3/10, FT+RAG 9/10 on the same
136
+ golden set; full analysis in `finetune/README.md`, build history and
137
+ bugs in `DESIGN_NOTES.md`
138
+ - [x] OpenAPI backend — read-only, GET-only by construction; validated
139
+ against the spec's own contract; petstore-verified in CI
140
+ - [x] HTTP serve layer: answer cache, grounded conversational summaries,
141
+ structured schema API, bearer auth — engine outcomes are always 200
142
+ payloads (an abstention is an answer, not an error)
143
+ - [x] Embeddable ask-widget (~15 KB gz, Shadow-DOM, one script tag) +
144
+ Discover-style playground: schema rail, time-range windows via
145
+ `query_range`, histogram/bar-chart results with rows one toggle away
146
+ - [ ] Loki (LogQL) backend; Datadog connector
147
+
148
+ ## Where this is going: apps that agents can actually use
149
+
150
+ The `Backend` protocol (introspect / validate / execute) is not
151
+ observability-specific. The same loop pointed at a product's own OpenAPI spec
152
+ or database turns any app into something an AI can query *safely*:
153
+
154
+ - **OpenAPI backend — shipped.** Introspects a product's own spec into the
155
+ catalog; questions compile into validated, GET-only API calls. Existing
156
+ OpenAPI->MCP generators dump every endpoint as a tool, which measurably
157
+ degrades agents (arXiv 2411.15399) and executes whatever the model asks.
158
+ queryglot's contribution is the missing layer: schema-grounded retrieval,
159
+ server-side validation, and abstention.
160
+ - **Customer-facing ask widget** — an embeddable search box backed by the
161
+ same engine: visitors' questions become validated queries against the
162
+ app's data, never hallucinated ones.
163
+ - **`llms.txt` + MCP endpoint generation** — one schema catalog, two
164
+ audiences: humans get the widget, agents get a typed, validated interface
165
+ instead of scraping. Discoverability for the agentic web, with execution
166
+ semantics — not just markup.
167
+
168
+ ## Known limits
169
+
170
+ - `metric_candidates` (unknown-metric detection) is regex-based and
171
+ best-effort; the backend parser owns syntax, this only improves error
172
+ messages. Complex PromQL may slip past it — never through the parser.
173
+ - Backend auto-routing is retrieval-strength-based; ambiguous questions
174
+ ("errors in checkout") can route to the wrong store. Pass `backend=` to pin.
175
+ - Synonym table is small and English-only, grown from eval failures.
176
+ - When a backend's catalog is smaller than the retrieval k (8), retrieval
177
+ sends the whole catalog and the abstention gate rarely fires — abstention
178
+ then rests on the validation layer.
179
+
180
+ ## License
181
+
182
+ MIT
@@ -0,0 +1,49 @@
1
+ [tool.poetry]
2
+ name = "queryglot"
3
+ version = "0.1.0"
4
+ description = "One question, many query languages. Schema-aware natural-language search over your observability stack, as an MCP server."
5
+ authors = ["Divyanshu Sharma <sharmadivyanshu24@gmail.com>"]
6
+ readme = "README.md"
7
+ license = "MIT"
8
+ repository = "https://github.com/sharmadivyanshu/queryglot"
9
+ keywords = ["mcp", "prometheus", "elasticsearch", "promql", "observability", "rag", "llm"]
10
+ packages = [{ include = "queryglot", from = "src" }]
11
+ include = [{ path = "src/queryglot/_static/**/*", format = ["sdist", "wheel"] }]
12
+
13
+ [tool.poetry.scripts]
14
+ queryglot = "queryglot.cli:main"
15
+ queryglot-mcp = "queryglot.mcp_server:main"
16
+ queryglot-serve = "queryglot.server:main"
17
+
18
+ [tool.poetry.dependencies]
19
+ python = "^3.11"
20
+ langgraph = "^1.2"
21
+ pydantic = "^2.9"
22
+ mcp = "^1.0"
23
+ fastapi = { version = "^0.115", optional = true }
24
+ uvicorn = { version = "^0.32", optional = true }
25
+
26
+ [tool.poetry.extras]
27
+ serve = ["fastapi", "uvicorn"]
28
+
29
+ [tool.poetry.group.dev.dependencies]
30
+ pytest = "^8.3"
31
+ pytest-asyncio = "^0.24"
32
+ ruff = "^0.8"
33
+ mypy = "^1.13"
34
+ httpx = "^0.27"
35
+
36
+ [tool.ruff]
37
+ line-length = 100
38
+ target-version = "py311"
39
+
40
+ [tool.ruff.lint]
41
+ select = ["E", "F", "I", "UP", "B", "SIM"]
42
+
43
+ [tool.pytest.ini_options]
44
+ testpaths = ["tests"]
45
+ asyncio_mode = "auto"
46
+
47
+ [build-system]
48
+ requires = ["poetry-core"]
49
+ build-backend = "poetry.core.masonry.api"
@@ -0,0 +1,30 @@
1
+ """queryglot — one question, many query languages.
2
+
3
+ Schema-aware natural-language search over observability backends, shipped as
4
+ an MCP server. Retrieval supplies YOUR schema (the part no model can know);
5
+ the model supplies syntax (the part a small fine-tune learns); the backend's
6
+ own parser has the final word.
7
+ """
8
+
9
+ from .backends.elastic import ElasticBackend
10
+ from .backends.openapi import OpenAPIBackend
11
+ from .backends.prometheus import PrometheusBackend
12
+ from .catalog import Catalog, SchemaItem
13
+ from .engine import Answer, Engine
14
+ from .llm import LLM, OpenAICompatibleLLM
15
+ from .retrieve import SchemaRetriever
16
+
17
+ __version__ = "0.1.0"
18
+
19
+ __all__ = [
20
+ "Answer",
21
+ "Catalog",
22
+ "ElasticBackend",
23
+ "Engine",
24
+ "LLM",
25
+ "OpenAICompatibleLLM",
26
+ "OpenAPIBackend",
27
+ "PrometheusBackend",
28
+ "SchemaItem",
29
+ "SchemaRetriever",
30
+ ]
File without changes