You are working on a Graphitron subgraph with an MCP-aware coding agent (Claude Code, Cursor), and you want the agent to understand your project: which tables the catalog holds, which @service classes exist, what the directive vocabulary means, and where to find the right pattern in the manual. mvn graphitron:dev already runs an MCP server for exactly this. Point your agent at it once and the agent stops guessing.
|
This is the companion to the dev loop. The same |
TLDR
| Step | What to run |
|---|---|
1. Start the dev server |
|
2. Register the server |
Run the copy-pasteable line the dev server prints on startup: |
3. Ask the agent |
Run the |
The MCP server is loopback-only and read-only: it exposes context about the project you are running graphitron:dev in, nothing else.
What the MCP server gives an agent
An MCP-aware agent connected to the server gets three kinds of context, all served off the same warm workspace the dev loop keeps current.
An about prompt (surfaced as the /mcp__graphitron__about slash command) that orients the agent on the dev loop and how to use the other tools. Run it first in a fresh session.
A directives resource, the Graphitron directive vocabulary, so the agent knows what @table, @field, @reference, @service, and the rest mean without you pasting the reference in.
A set of tools the agent calls to answer questions:
| Tool | What it answers |
|---|---|
|
Natural-language retrieval over the bundled manual ("which directive joins two tables?"). Returns the matching passages with a link into this site, so the agent finds the right pattern without already knowing the vocabulary to grep for. |
|
Semantic, fuzzy discovery over your jOOQ catalog ("where are customer addresses stored?"). Returns the most relevant tables ranked by similarity, by schema-qualified SQL name. Feed a hit straight into |
|
Lists the tables in the catalog. |
|
Full column / key / foreign-key detail for one table. |
|
Describes the classified GraphQL schema. |
|
List the |
|
Traverses the cross-reference edges between schema elements and their backing Java / jOOQ. |
|
The current schema validation diagnostics, the same |
|
Dev-loop status (ports, warm state). |
|
Runs a GraphQL query or mutation against your generated resolvers in-process, on the dev database you configure, and returns exactly what the query returns. Mutations always roll back. Appears only when a dev database is configured; see Run a query without an app server below. |
|
|
Run a query without an app server
Point graphitron at your database once, in the plugin configuration or via environment variables, and the MCP execute tool runs a GraphQL query or mutation against your generated resolvers in-process: no Quarkus, no deploy, and the agent (or you) gets back exactly what the query returns. Mutations run in a transaction that is always rolled back, so you can probe writes freely without changing data.
The configuration is plain connection coordinates. In the plugin:
<devDatabase>
<url>jdbc:postgresql://localhost:5432/mydb</url>
<user>dev</user>
<password>dev</password>
<dialect>POSTGRES</dialect> <!-- or ORACLE; always explicit -->
</devDatabase>
Or via environment variables, which override the POM so credentials stay out of the checked-in file: GRAPHITRON_DEV_DB_URL, GRAPHITRON_DEV_DB_USER, GRAPHITRON_DEV_DB_PASSWORD, GRAPHITRON_DEV_DB_DIALECT. The JDBC driver is one your project already has: any scope works (your application’s runtime dependency, or the test-scope driver your database tests use; Quarkus apps typically only have the latter in their Maven graph).
Row-level security still applies. If your schema mounts identity (graphitron’s <sessionState> connect hook), give the dev tool a claims payload via GRAPHITRON_DEV_CLAIMS: the same string your connect function expects in production (claims JSON, or a genuinely issued dev token if your function verifies signatures). Use @/path/to/file to keep tokens out of environment listings; the file is re-read on every call, so edits apply immediately. The tool runs your real connect function and sees only what the mounted identity is permitted, just like your running service. If claims are required and missing, the tool says so loudly instead of running unsecured; if your connect function rejects the payload, you get its error message verbatim, so you can fix the payload and retry.
No database configured? The execute tool simply does not appear; every other dev tool (schema, catalog, diagnostics, docs) works with no database at all.
Three current limits: federation subgraphs are not yet supported by execute (every other tool works on them); writes cannot be persisted (rollback is unconditional by design); and the rollback guarantee covers mutation-field transactions, so a query-path @service or @routine that writes runs outside it, exactly as it runs outside graphitron’s transaction demarcation in production.
Connect your agent
The server speaks the Model Context Protocol over Streamable HTTP at http://127.0.0.1:8488/mcp. Any MCP-aware agent that supports HTTP transport can connect.
Claude Code
The dev server prints a copy-pasteable line on startup:
claude mcp add --transport http graphitron http://127.0.0.1:8488/mcp
Run it once and Claude Code registers the graphitron server. Alternatively, commit a .mcp.json at the project root so anyone who clones the repo gets the server with zero configuration:
{
"mcpServers": {
"graphitron": {
"type": "http",
"url": "http://127.0.0.1:8488/mcp"
}
}
}
The graphitron-sakila-example project ships exactly this file, so cloning it needs no MCP setup at all.
Cursor and other agents
Any MCP client that accepts an HTTP endpoint works: register a server named graphitron pointing at http://127.0.0.1:8488/mcp with transport type HTTP (sometimes labelled "Streamable HTTP" or "http"). The shape is the same as the .mcp.json above; consult your agent’s MCP configuration docs for where that config lives.
Port and lifecycle
The MCP port is fixed at 8488 (the LSP’s is 8487) and, unlike the LSP port, is not overridable. It stays a well-known value so a committed .mcp.json never drifts. If 8488 is already taken, typically a second graphitron:dev for another project, the dev server fails fast on startup with a message naming the conflict rather than silently rebinding, so a stale .mcp.json never points an agent at the wrong project’s server. Stop the other session occupying the port, then retry.
The server is part of the one graphitron:dev JVM: no daemon, no separate process to manage. Ctrl+C on the dev goal closes the MCP server along with the LSP socket and the watchers.
See also
-
The dev loop (Quarkus + LSP): the editor-facing half of the same
graphitron:devprocess. -
Dev loop reference (architecture docs): how the
devgoal wires the LSP, MCP server, watchers, and generator dispatch into one JVM.