Skip to content

feat(cli): add MongoDB aggregate query surface (CLI + MCP)#346

Open
kevinmessiaen wants to merge 18 commits into
mainfrom
feat/mongo-query-tool
Open

feat(cli): add MongoDB aggregate query surface (CLI + MCP)#346
kevinmessiaen wants to merge 18 commits into
mainfrom
feat/mongo-query-tool

Conversation

@kevinmessiaen

@kevinmessiaen kevinmessiaen commented Jul 9, 2026

Copy link
Copy Markdown
Collaborator

Summary

Adds a MongoDB aggregate query surface to ktx, exposed through both the CLI (ktx mongo-query) and the MCP context tool (mongo_query), mirroring the existing SQL query path.

  • Connector: adds a read-only aggregate query surface to the MongoDB connector.
  • MCP: declares the mongoQuery context port contract, builds the port over the shared connector factory, and registers the mongo_query tool.
  • CLI: adds the runKtxMongoQuery runner, registers the ktx mongo-query command, and exports runKtxMongoQuery as a public API to match runKtxSql.
  • Shared IO: extracts result-table formatters out of sql.ts into io/result-table.ts so SQL and Mongo share one rendering path.
  • Telemetry: adds the mongo_query_completed event (Node ↔ Python schema kept in parity).
  • Docs: documents the ktx mongo-query command.

Notes

  • Pipelines are enforced read-only. $out/$merge are rejected at the top level; MongoDB itself forbids them in $facet/$lookup/$unionWith sub-pipelines, so the top-level check is sufficient.
  • The Mongo read path routes through one shared runMongoQuery execution seam, used by both the CLI runner and the MCP port.

Review & cleanup pass

The last two commits apply a multi-agent review of the branch:

  • Types consolidated onto the shared connector interface. executeQuery? now lives on KtxScanConnector alongside the sibling executeReadOnly?, and KtxMongoQueryInput/KtxMongoQueryResult live in context/scan/types.ts next to the SQL query types. The runner narrows to the connector by capability instead of an as unknown as cast, and the duplicate request/response type shapes and a pass-through wrapper were removed.
  • Docs fix. The --output default is TTY/CI/KTX_OUTPUT-derived, not unconditionally pretty; corrected in both the ktx mongo-query and ktx sql references.
  • Test coverage added. parseLimitOption bounds, the database override path, empty result sets, bigint/plural-row/empty-header rendering, and mongo_query_completed telemetry field correctness on both the ok and error outcomes.

Verification

  • Type-check, dead-code (Biome + Knip default/production), and pre-commit hooks pass.
  • Mongo-query test surface (CLI runner, MCP port, connector, rendering, telemetry) passes.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Ga2tvQ2YCEphmY8HM5Guzq

kevinmessiaen and others added 15 commits July 6, 2026 16:15
The wrong-driver test's fake createConnector ignored the requested id
and always returned a mongodb connector, so the driver guard never
ran; the rejection came incidentally from assertConnection deep in the
connector. It also asserted KtxQueryError, but the guard throws
KtxExpectedError. Dispatch the fake by id and assert the guard's own
error type and message.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BdUJSmjqGoksdc45ZZJiVY
Expose the mongoQuery port as a callable MCP tool so agents can run
aggregation pipelines against MongoDB connections directly, since
MongoDB collections are not queryable via sql_execution.
Closes a coverage gap for the mongo_query MCP tool and fixes Knip's
default-mode unused-export flag on KtxMongoQueryMcpPort, which had no
cross-file consumer before this test imported it.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BdUJSmjqGoksdc45ZZJiVY
Move formatValue/printJson/printPlain/printPretty/printResultTable and
the KtxResultTable interface out of sql.ts into io/result-table.ts so
the upcoming mongo-query command can reuse them verbatim.
Adds the strict mongo_query_completed schema (driver, isDemoConnection,
stageCount, durationMs, outcome, errorClass) for the upcoming
ktx mongo-query command, registered in both the catalog object and the
name/description/fields catalog list, and mirrors it to the Python
daemon schema copy.
@vercel

vercel Bot commented Jul 9, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
ktx-docs-site Ready Ready Preview, Comment Jul 19, 2026 12:57pm

Request Review

@codecov-commenter

codecov-commenter commented Jul 9, 2026

Copy link
Copy Markdown

Route the Mongo read path through one canonical request/result shape and
remove the `as unknown as` narrowing flagged in review.

- Add optional executeQuery to KtxScanConnector and narrow by capability
  in the runner, replacing the double cast with a driver + method guard.
- Move KtxMongoQueryInput/KtxMongoQueryResult into context/scan/types.ts;
  delete the duplicate runner request type, the inline MCP-port input, and
  the KtxMongoQueryResponse alias. KtxMongoQueryArgs now extends the base.
- Inline the pass-through executeMongoQuery wrapper.
- Correct the --output default in the mongo-query and sql CLI docs: it is
  TTY/CI/KTX_OUTPUT-derived, not unconditionally pretty.
- Add tests: database override, empty result, parseLimitOption bounds,
  bigint/plural-row/empty-header rendering, and mongo_query_completed
  telemetry fields on both outcomes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ga2tvQ2YCEphmY8HM5Guzq
Now that KtxMongoQueryArgs extends KtxMongoQueryInput and the runner takes
that type, pass the args/input object straight through instead of rebuilding
it field by field. assertSafeConnectionId returns its input verbatim, so the
`{ ...input, connectionId }` spread was re-asserting an equal value.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ga2tvQ2YCEphmY8HM5Guzq
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants