Skip to content

feat: resolve MCP pipeline source from project config - #80

Open
mingjerli wants to merge 1 commit into
mainfrom
feat/mcp-config-resolution
Open

feat: resolve MCP pipeline source from project config#80
mingjerli wants to merge 1 commit into
mainfrom
feat/mcp-config-resolution

Conversation

@mingjerli

Copy link
Copy Markdown
Owner

Step 1 of packaging clgraph as a coding-agent plugin: A1 (config resolution + soft-fail startup) and A5 (clgraph-mcp console script).

Why

Plugin hosts spawn the MCP server with no arguments, but --pipeline was required=True in both server.py:303 and cli.py:258. A missing value killed the process during the MCP handshake, which surfaces in clients as a dead server with no explanation — invisible to the agent, unactionable for the user.

What changed

New clgraph.mcp.config answers one question: what has this project been configured to index? First hit wins:

  1. --pipeline / --dialect arguments
  2. $CLGRAPH_PIPELINE / $CLGRAPH_DIALECT
  3. clgraph.toml (top-level sql_dir, dialect)
  4. [tool.clgraph] in pyproject.toml
  5. A cached .clgraph/pipeline.json
  6. None

Paths resolve against the config file's own directory, not the cwd — the server may be spawned from anywhere in the tree.

Soft-fail startup. create_mcp_server() and run_mcp_server() accept pipeline=None. An unconfigured server still registers all 14 tools with their real schemas; each returns a message naming the fix. An agent that can read the error recovers on its own.

No silent discovery. Directory sniffing (models/, sql/, queries/) is deliberately absent. Guessing a source is only safe when the dialect is also known, and discovery now belongs in setup, where it proposes to a human.

clgraph-mcp console script, so client configs invoke the server directly instead of through python -m.

Breaking change

The dialect is no longer defaulted to bigquery when indexing SQL files. clgraph-mcp --pipeline ./queries/ without --dialect now exits with guidance.

sqlglot parses most of a corpus under the wrong grammar without erroring, so the old fallback produced lineage graphs that looked right and were not — the worst failure mode for a tool an agent will trust. JSON pipelines are unaffected; they carry their own dialect.

Two CLI tests encoded the old default and were updated, with comments explaining why.

Test plan

  • tests/test_mcp_config.py — 22 new tests: full resolution matrix, precedence, path resolution from nested cwds, kind classification, and the refuse-to-guess guards
  • tests/test_mcp.py — 14 new tests: unconfigured server boots, all 14 tools registered with intact schemas, every tool returns the actionable message, no per-table resources, env-var configuration, dialect refusal
  • Full suite: 1699 passed, 40 skipped, 2 xfailed — no regressions
  • make pre-commit clean; ty back to its 52-diagnostic baseline
  • Manual end-to-end in a scratch project: unconfigured resolve returns None and 14 tools still register; missing dialect refuses with guidance; clgraph.toml with a dialect traces staging.users.emailraw.users.email

Docs

README MCP section rewritten (it published the now-removed python -m clgraph.mcp --pipeline invocation and the old Desktop config), plus CHANGELOG entries. The docs-site submodule PR and the remaining pages come with step 7.

Next

Step 2 — A6 + A7, clgraph detect and clgraph init, which is where the dialect question actually gets asked.

Plugin hosts spawn the MCP server with no arguments, but --pipeline was
required and a missing value killed the process during the MCP handshake
— which surfaces in clients as a dead server with no explanation.

Add clgraph.mcp.config, which answers "what has this project been
configured to index?" in order: --pipeline argument, $CLGRAPH_PIPELINE,
clgraph.toml, [tool.clgraph] in pyproject.toml, then a cached
.clgraph/pipeline.json. An unconfigured project resolves to None and the
server starts anyway: all 14 tools register with their real schemas and
return a message naming the fix, so an agent can recover on its own.

Deliberately absent: silent directory sniffing. Guessing a SQL directory
is only safe when the dialect is also known, and the dialect is now never
defaulted. sqlglot parses most of a corpus under the wrong grammar without
erroring, so the old bigquery fallback produced lineage graphs that looked
right and were not. Pointing at SQL files without a dialect is now an
error naming the fix. JSON pipelines are unaffected — they carry their own.

Also adds the clgraph-mcp console script so client configs can invoke the
server directly rather than through python -m.

Breaking: `--pipeline <dir>` without `--dialect` no longer parses as
BigQuery. Two CLI tests encoded that default and were updated.
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.

1 participant