Provides a governed graph over databases, APIs, files, and code to allow AI agents to discover, validate, and execute tasks through GraphQL and MCP.
Also known as dosco/graphjin
- Stars
- 3,236
- Tools
- 3
- Downloads, 30 days
- —
- Latest version
- —
- Last commit
- Nov 13, 2026
- License
- Apache-2.0
What is GraphJin MCP?
GraphJin provides a governed graph over databases, APIs, files, and code to allow AI agents to discover, validate, and execute tasks through GraphQL and MCP. It exposes 3 tools, such as query_catalog, graphql_help, gj_workflow_execution.
Summary generated from the project's README
About GraphJin MCP server
GraphJin acts as a compiler and runtime that creates a governed graph across diverse data sources including databases, files, and source code. It is designed for developers and organizations that want to provide AI agents with structured access to systems like PostgreSQL, MySQL, MongoDB, Snowflake, and S3 without granting raw credentials. By exposing these connections through GraphQL and the Model Context Protocol, the system allows agents to discover schemas, validate queries, and execute approved tasks within defined security boundaries.
Users can deploy GraphJin locally via npm, Homebrew, or Docker, or connect to hosted instances using OAuth for remote access. The server supports various AI models, from local 7B versions to Claude and GPT-4. It provides specialized tools such as ask_graphjin_agent for direct instructions and gj_watch for monitoring data changes through cursor-paginated subscriptions. This setup ensures that every agent action is checked against an execution ledger and adheres to established security policies.
What you can do with it
- 1Automated data discoveryAn AI agent can search a catalog to understand available data relationships before attempting to write queries.
- 2Continuous data monitoringDevelopers can set up persistent watches that trigger events when specific database conditions are met.
- 3Secure agentic task executionUsers can send natural language instructions to a built-in agent that returns evidence-backed answers.
- 4Multi-source data integrationA single interface can query across operational databases, object stores, and local files simultaneously.
Written from the project's README. Every use case is checked against a quote from it.
How to install GraphJin MCP
Formats verified 10 Nov 2026Install GraphJin MCP in Claude Code
$ claude mcp add graphjin -- npx -y graphjinInstall GraphJin MCP in Cursor
~/.cursor/mcp.json
{
"mcpServers": {
"graphjin": {
"command": "npx",
"args": [
"-y",
"graphjin"
]
}
}
}Install GraphJin MCP in VS Code
.vscode/mcp.json
{
"servers": {
"graphjin": {
"type": "stdio",
"command": "npx",
"args": [
"-y",
"graphjin"
]
}
}
}Install GraphJin MCP in Claude Desktop
claude_desktop_config.json
{
"mcpServers": {
"graphjin": {
"command": "npx",
"args": [
"-y",
"graphjin"
]
}
}
}Install GraphJin MCP in Codex
~/.codex/config.toml
[mcp_servers.graphjin] command = "npx" args = ["-y", "graphjin"]
Install GraphJin MCP in Gemini CLI
~/.gemini/settings.json
{
"mcpServers": {
"graphjin": {
"command": "npx",
"args": [
"-y",
"graphjin"
]
}
}
}GraphJin MCP tools 3
Detected from the READMEquery_cataloggraphql_helpgj_workflow_execution
| query_catalog | — | |
| graphql_help | — | |
| gj_workflow_execution | — |
Automated checks
Ran Nov 12, 2026Full report →Passed our automated checks. That is not a security audit: read the code and give the server the narrowest access it needs. How checks work
- Source repository linked and reachablePass
- Open source license (OSI)Pass
- Commit or release in the last yearPass
- Package name not close to a popular packagePass
- Remote endpoint uses HTTPSNot checked
- Destructive tools are labelledPass
- No hidden instructions to the modelPass
- No critical advisory in the package or its dependenciesNot checked
README
View on GitHubGraphJin — One Governed Graph for Your AI Agents
GraphJin is a compiler and runtime that gives AI agents one governed graph over the systems a real company already has: databases, warehouses, files, source code, workflows, metadata, and security policy. Instead of handing an agent raw credentials and hoping it guesses correctly, GraphJin exposes that graph through GraphQL + MCP: the agent discovers before acting, validates queries, runs approved work, observes runtime status — and every answer is checked against an execution ledger before it leaves the server.
It is not only for agents. GraphJin is still a high-performance GraphQL-to-database compiler, Go library, standalone API service, REST/OpenAPI gateway, and real-time subscription server. The agent use case is where everything comes together: the same compiler that serves your apps can also give AI a smart, auditable way to work across data, code, and operations.
Works with PostgreSQL, MySQL, MongoDB, SQLite, Oracle, MSSQL, Snowflake, Redshift, BigQuery, Apache Cassandra / Amazon Keyspaces, S3/GCS/local files, CodeSQL source indexes - and models from Claude/GPT-4 to local 7B models.
Why GraphJin For Agents
- A built-in agent, one call away - POST one instruction to
/api/v1/agent(or call theask_graphjin_agentMCP tool) and GraphJin runs the discovery loop itself - as the caller, under the caller's permissions - and returns a typed, evidence-backed answer. See Server-Side Agent. - One governed surface for many systems - Query operational databases, warehouses, MongoDB, object stores, local files, CodeSQL source indexes, workflows, and GraphJin system roots through GraphQL and MCP.
- Smart discovery before action - Agents start with
query_catalog(search: "<user instruction>"),graphql_help, relationship evidence, examples, config recipes, and safety notes before writing or running queries. - Guarded action, not raw access - Source-mode access, query allow-lists, read-only boundaries, policy-aware MCP tools, local encrypted secrets, and
gj_configpreview/apply keep changes auditable. - Operational awareness -
gj_security,gj_runtime, and the built-in console expose policy and bounded runtime status so agents can check what is safe before they act. - Standing questions, not just answers - Hand a cursor-paginated subscription to
gj_watchand GraphJin keeps answering it under the owner's permissions, resumes from persisted cursors across restarts, treats absence as a first-class event, and files what it finds in a durable inbox (gj_watch_event), a webhook, or a workflow. Evaluation runs on database polls, not model calls - a model writes the watch once, and nothing calls one again unless you turn on optional per-watch triage. See Watches. - Durable memory - Saved queries, fragments, and workflows live in the owner-scoped
gj_artifactsstore. Normal watches are durable by default; explicit ephemeral watches use TTL leases.
Installation
npm (all platforms)
npm install -g graphjin
macOS (Homebrew)
brew install dosco/graphjin/graphjin
Windows (Scoop)
scoop bucket add graphjin https://github.com/dosco/graphjin-scoop
scoop install graphjin
Linux
Download .deb/.rpm from releases
Docker
docker pull dosco/graphjin
Docker — as an agent environment
The same binary also ships as a graded environment for training and evaluating agents. It boots ready with nothing mounted: the demo world and a 113-task verified suite are built in.
docker run -d -p 8090:8090 --tmpfs /tmp:size=1g dosco/graphjin:env-latest
/health says what it is — build, suite fingerprint, dataset fingerprint,
reward contract, and whether the suite matches the world it is served on.
/tmp must be writable: each world provisions its own database there.
See the environment docs for the full story.
Try It Now
One command, no clone, no Docker. The binary ships with a built-in demo — a SaaS company ops app (accounts, subscriptions, invoices, support tickets) on SQLite with seeded data, saved queries, and workflows:
graphjin serve --demo
The demo project is extracted to ./graphjin-demo, and its state lives under
./graphjin-demo/demo/. Delete the demo/ folder to reset the data, or
delete ./graphjin-demo entirely for a fresh copy. You'll see output like
this:
GraphJin started
───────────────────────
Web UI: http://localhost:8083/
GraphQL: http://localhost:8083/api/v1/graphql
REST API: http://localhost:8083/api/v1/rest/
Workflows: http://localhost:8083/api/v1/workflows/<name>
MCP: http://localhost:8083/api/v1/mcp
Ask the built-in agent
With a model API key in ./.env (OPENAI_API_KEY, ANTHROPIC_API_KEY, or GOOGLE_APIKEY), the same command switches into agentic mode and enables GraphJin's built-in agent - one instruction in, a typed, evidence-backed answer out:
curl -sS localhost:8083/api/v1/agent \
-H 'content-type: application/json' \
-d '{"instruction": "Which account is most at risk of churning?"}'
Answers come back as {status, answer, data, evidence, actions, next}, grounded by server-side protocol guards. You can also chat with it in the built-in web console at localhost:8083/agent — it streams every tool call live as it works. See Server-Side Agent below, AGENTIC.md, and graphjin.com/agentic/server-agent.
More demo verticals
The bigger demos live in the repo — clone it and pass --path:
git clone https://github.com/dosco/graphjin
cd graphjin
graphjin serve --demo --path examples/webshop # classic GraphQL starter (Postgres)
graphjin serve --demo --path examples/coffee-roastery # flagship agentic demo (Postgres + BigQuery-emu + CodeSQL)
Each demo keeps its state under <path>/demo/ and reuses it on later starts.
A MySQL corrugated-box plant with JWT roles and a PCB fab spanning Postgres +
Snowflake-emu + MongoDB + a file source + an OpenAPI supplier API live in
examples/, each with an end-to-end smoke suite
(make smoke-all runs them all). The full tour is at
https://graphjin.com/start/demos/.
Add GraphJin To Your AI Client
Local / Dev
Use GraphJin's helper when you want one command that normalizes the URL, probes auth, and installs the right Codex or Claude config:
graphjin mcp add codex
graphjin mcp add claude
graphjin mcp add all http://localhost:8080
Defaults are client=codex, server=http://localhost:8080, and project scope.
The command normalizes the server to http://localhost:8080/api/v1/mcp. Local
non-TLS HTTP is correct for loopback development; hosted servers should use
HTTPS.
If you prefer native client commands, add GraphJin's Streamable HTTP endpoint directly:
codex mcp add graphjin --url http://localhost:8080/api/v1/mcp
claude mcp add --transport http graphjin http://localhost:8080/api/v1/mcp
GraphJin's /api/v1/mcp endpoint is Streamable HTTP, so Claude should use
--transport http for GraphJin. SSE is only for older/custom MCP servers.
Use --global when you want the MCP connection available outside the current project:
graphjin mcp add codex --global
Codex can also add non-URL stdio MCP servers with the generic command shape:
codex mcp add <server-name> -- <command> [args...]
Hosted GraphJin With OAuth
When mcp.oauth.enabled: true is configured on a hosted GraphJin server, modern
MCP clients can add it by URL and handle OAuth login themselves:
codex mcp add graphjin --url https://graphjin.example.com/api/v1/mcp
claude mcp add --transport http graphjin https://graphjin.example.com/api/v1/mcp
This is the native remote-MCP path. GraphJin serves OAuth protected-resource
metadata, authorization-server metadata, DCR/CIMD discovery, and MCP 401
challenges so the client can discover login automatically. See the official
OpenAI Docs MCP quickstart for the
Codex mcp add --url flow and the
Claude Code MCP docs for
Claude's HTTP transport and authentication flow.
For legacy/custom SSE servers, use Claude's SSE transport explicitly:
claude mcp add --transport sse <name> <url>
claude mcp add --transport sse private-api https://api.company.com/sse \
--header "X-API-Key: your-key-here"
Legacy / Current auth_login Fallback
If a server still uses GraphJin's current auth_login device-code flow instead of standards OAuth, graphjin mcp add detects that automatically:
graphjin mcp add codex https://graphjin.example.com
The command opens the device-code login, saves ~/.config/graphjin/client.json, and installs a credential-free local proxy config for the AI client. Re-run graphjin mcp setup https://graphjin.example.com later only when you want to refresh or rotate that saved CLI/proxy token.
The deprecated aliases still work for scripts:
graphjin mcp install codex https://graphjin.example.com
graphjin mcp plugin install https://graphjin.example.com # deprecated Claude alias
Authenticate The CLI
Before graphjin cli can talk to a server, point it at one. There are no --server or --token flags — both come from a single saved config file (~/.config/graphjin/client.json, mode 0600):
graphjin cli setup http://localhost:8080 # local dev, no auth needed
graphjin cli setup https://graphjin.example.com # signs in via the server's OIDC IdP
What setup does, depending on the server:
- No built-in login (the server has
auth_login.enabled: false): saves only the URL. CLI calls send noAuthorizationheader. - Built-in login enabled: kicks off an RFC 8628 device-code flow. The CLI prints a verification URL + short code, opens your browser, you sign in with the configured identity provider (Google, Okta, Keycloak, Auth0-as-IdP, Azure AD — anything OIDC), and the server mints a 30-day JWT. Both URL and JWT are saved to
client.json.
After setup every graphjin cli ... command just works:
graphjin cli health
graphjin cli query list
graphjin cli schema tables
graphjin cli setup show # print the saved config (token redacted)
graphjin cli setup logout # delete client.json
graphjin cli setup # re-run sign-in against the same server (refresh token)
To enable built-in login, set this on the server:
auth:
type: jwt
jwt:
secret: "long-random-shared-secret" # used to sign and verify local JWTs
auth_login:
enabled: true
audience_graphjin: true # shorthand for audience: "graphjin-cli"
oidc:
issuer_url: "https://accounts.google.com"
client_id: "..."
client_secret: "..." # or $GJ_AUTH_LOGIN_OIDC_CLIENT_SECRET
allowed_domains: ["example.com"] # optional allow-list
mcp:
oauth:
enabled: true
mode: builtin # reuses auth_login identity
scopes: ["mcp"]
Successful authentication is recorded in structured logs with the verified email and name claims (when present), giving you a clean audit trail of who called every endpoint.
Getting started
To use GraphJin with your own databases you have to first create a new GraphJin app, then configure it using its config files and then launch GraphJin.
Step 1: Create New GraphJin App
graphjin serve new my-app
Step 2: Start the GraphJin Service
graphjin serve --path ./my-app
Step 3: Add GraphJin to an AI client
graphjin mcp add claude http://localhost:8080
Step 4: Ask Claude questions like:
- "What tables are in the database?"
- "Show me all products under $50"
- "List customers and their purchases"
- "What's the total revenue by product?"
- "Find products with 'wireless' in the name"
- "Add a new product called 'USB-C Cable' for $19.99"
How It Works
- Connects to database - Reads your schema automatically
- Discovers relationships - Foreign keys become navigable joins
- Exposes metadata - Built-in
gj_*tables make discovered databases, tables, columns, relationships, functions, and indexes queryable when their feature capabilities are enabled - Indexes source code - CodeSQL turns tree-sitter syntax trees and database references into a managed SQLite database
- Exposes MCP tools - Teach any LLM the query syntax
- Runs JS workflows - Chain multiple GraphJin MCP tools in one reusable workflow
- Compiles to SQL - Every request becomes a single optimized query
No resolvers. No ORM. No N+1 queries. Just point and query.
CodeSQL: Query Source Code Like a Database
CodeSQL is a managed source kind for source trees. Configure a source folder and GraphJin creates a SQLite cache under config/codesql/, indexes it with tree-sitter, and updates it on restart. In development it also watches for changes while the service runs; in production live watching is disabled.
sources:
- name: app
kind: database
type: postgres
connection_string: postgres://app:secret@db/app
default: true
- name: code
kind: code
path: /srv/app
infer_db_refs: true
tables:
- name: users
source: app
- name: gj_code
source: code
read_only: true
GraphJin exposes CodeSQL through one ordinary GraphQL root, gj_code. Use kind to select files, symbols, references, imports, database references, docs, parse errors, change sets, and locks:
query {
gj_code(where: { kind: { eq: "symbol" }, name: { iregex: "handler|resolver" } }, limit: 20) {
name
symbol_kind
language
start_row
path
hash
}
}
GraphJin's built-in catalog creates gj_catalog according to the deployment-mode defaults; no source entry is required. Schema, catalog, entrypoint, capability, workflow, and system metadata are catalog items; table and column metadata are selected by kind. When one CodeSQL source is active, GraphJin links catalog items to code references automatically:
query {
gj_catalog(where: { kind: { eq: "column" }, table_name: { eq: "users" }, column_name: { eq: "email" } }) {
database_name
table_name
column_name
gj_code {
kind
ref_kind
path
symbol_id
}
}
}
This is where the model gets genuinely powerful: the same agent can inspect production data systems and the code that operates them. It can ask, "which handlers touch customer invoices?", "what tables do these workflows depend on?", or "show me the imports and call sites near this data path" without switching tools or inventing a new backend.
What AI Can Do
Simple queries with filters:
{ products(where: { price: { gt: 50 } }, limit: 10) { id name price } }
Nested relationships:
{
orders(limit: 5) {
id total
customer { name email }
items { quantity product { name category { name } } }
}
}
Aggregations:
{ products { count_id sum_price avg_price } }
Analytics directives:
{
orders {
account_id
month
total
running_total: total @running(aggregate: sum, by: "account_id", orderBy: { month: asc })
moving_avg_total: total @moving(aggregate: avg, rows: 6, by: "account_id", orderBy: { month: asc })
previous_total: total @previous(by: "account_id", orderBy: { month: asc })
rank_by_total: total @rank(by: "account_id", order: desc)
}
}
Use analytics directives when each original row should remain visible while adding report metrics such as running totals, moving averages, previous/next values, first/last values, and rank within a group. Ordinary one-row-per-group summaries still use distinct plus aggregate fields. Supported SQL databases validate analytics support at compile time; MongoDB and known-old database versions return clear errors.
Mutations:
mutation {
products(insert: { name: "New Product", price: 29.99 }) { id }
}
PostgreSQL and SQLite also support an update-free insert conflict policy for a single row. GraphJin infers one supplied unique key and returns the stored row unchanged on conflict:
mutation {
users(insert: { email: "ada@example.com", full_name: "Ada" }, on_conflict: get) {
id email full_name
}
}
Spatial queries:
{
stores(where: { location: { st_dwithin: { point: [-122.4, 37.7], distance: 1000 } } }) {
name address
}
}
Real-time Subscriptions
Get live updates when your data changes. For databases with batching support, GraphJin handles thousands of concurrent subscribers with a single database query - not one per subscriber.
subscription {
orders(where: { user_id: { eq: $user_id } }) {
id total status
items { product { name } }
}
}
Why it's efficient:
- Traditional approach: 1,000 subscribers = 1,000 database queries
- GraphJin: 1,000 subscribers = 1 optimized batch query
- Automatic change detection - updates only sent when data actually changes
- Built-in cursor pagination for feeds and infinite scroll
Dialects that do not implement GraphJin's batched polling path are listed as unsupported in the database support matrix.
Subscribe over WebSockets (graphql-ws / graphql-transport-ws subprotocols) or Server-Sent Events — set Accept: text/event-stream on a POST /api/v1/graphql request and GraphJin streams event: next frames for each result, terminated by event: complete. Works from Node.js, Go, or any browser EventSource / WebSocket client.
Filesystem Tables (Local, S3, GCS)
Object stores show up as ordinary tables in your GraphQL schema. Declare them in config and they get the same query surface as a database table — no per-storage GraphQL plumbing on your side.
sources:
- name: avatars
kind: filesystem
backend: s3
bucket: my-bucket
prefix: avatars/
region: us-east-1
presign_ttl: 15m
- name: invoices
kind: filesystem
backend: gcs
bucket: invoices
prefix: 2026/
- name: uploads_local
kind: filesystem
backend: local
root: /var/lib/graphjin/uploads
tables:
- name: avatars
source: avatars
read_only: true
- name: invoices
source: invoices
read_only: true
- name: uploads_local
source: uploads_local
Every filesystem table exposes the same columns regardless of backend:
{ avatars(
where: { key: { like: "users/%" } }
order_by: { key: asc }
limit: 50
) {
key size content_type modified_at url
}
}
{ avatars(id: "users/42.png") {
key size url data # data is base64 because the field was selected
}
}
The legacy prefix, key, and inline_data arguments remain accepted, but new callers should use the normal GraphJin read surface: id, where, order_by, limit, offset, first, last, after, and before.
For cursor pagination, request the standard root cursor field, e.g. avatars_cursor, and pass it back through after: $cursor.
url is a presigned GET URL by default (15 min, configurable per table). Auth follows the standard credential chain: AWS env / ~/.aws / IRSA / EC2 IMDS for S3, Application Default Credentials for GCS — never embedded in GraphJin config.
Slim builds drop SDK weight: -tags no_s3 or -tags no_gcs excludes either backend. Custom backends register through core.OptionSetFilesystemBackend(name, factory) — same SDK GraphJin uses for the built-ins.
File Uploads
The GraphQL endpoint accepts multipart bodies per the graphql-multipart-request-spec. Files can be inlined as base64 (default) or streamed straight to a filesystem table:
uploads:
enabled: true
storage: avatars # name of a filesystems[] entry; omit to inline as base64
storage_key_prefix: "{date}/" # {date} → YYYY/MM/DD
max_size: 25_000_000
allowed_mime: ["image/*", "application/pdf"]
When storage is set, the file body is written to the backend and the GraphQL variable becomes a stable reference — mutations persist this directly into a JSONB column:
{ "key": "2026/05/08/abc123.png",
"url": "https://s3.../...?presigned",
"size": 12345,
"content_type": "image/png" }
When storage is empty the variable carries the bytes inline as {filename, content_type, size, data} (base64) — useful for small uploads going straight into bytea.
Apollo Federation v2
GraphJin can register as a federation subgraph so it composes with other services behind Apollo Router / Cosmo / Hive Gateway:
federation:
enabled: true
version: "v2.5"
keys:
users: ["id"] # auto-derived from PKs by default
orders: ["id", "tenant_id"] # composite keys via override
shareable: ["Tag.name"] # field-level @shareable
inaccessible: ["Users.encrypted_password"]
_service { sdl } returns a federation-flavoured SDL with @link, @key, @shareable, @inaccessible, @tag, _Service, and _Entity. Composition succeeds out of the box; _entities resolution is on the roadmap (the engine returns a clear error today, so gateways see the gap rather than silent failures).
GraphJin MCP questions
How do I add GraphJin MCP to Claude Code?
Run claude mcp add graphjin -- npx -y graphjin in your terminal. Add --scope user to make it available in every project.
How do I add GraphJin MCP to Cursor?
Open ~/.cursor/mcp.json and add the server under mcpServers, using the Cursor config shown in the install section above.
What tools does GraphJin MCP provide?
It exposes 3 tools, including query_catalog, graphql_help, gj_workflow_execution.
How can I add GraphJin to my AI client?
You can use the GraphJin helper command graphjin mcp add for Codex or Claude, or add the Streamable HTTP endpoint directly to your client.
What databases does GraphJin support?
It works with a wide range of systems including PostgreSQL, MySQL, MongoDB, SQLite, Oracle, MSSQL, Snowflake, Redshift, BigQuery, and Apache Cassandra.
Does GraphJin provide a built-in agent?
Yes, you can trigger a built-in agent by sending a POST request to the /api/v1/agent endpoint or by calling the ask_graphjin_agent MCP tool.