
neo4j-graphql-skill
Build and configure a GraphQL API backed by Neo4j using @neo4j/graphql v7 (current) or v5 (LTS). Covers Neo4jGraphQL constructor, getSchema(), assertIndexesAndConstraints(), type definitions with @node, @relationship (IN/OUT/UNDIRECTED), @cypher for custom resolvers, @authorization/@authentication for JWT/JWKS security, auto-generated queries/mutations, OGM programmatic access, subscriptions via CDC, and Apollo Federation. Use when writing typeDefs, securing fields, or wiring Neo4j to Apollo Server. Does NOT handle raw Cypher outside resolvers — use neo4j-cypher-skill. Does NOT cover Spring Data Neo4j entity mapping — use neo4j-spring-data-skill.
- Installs
- 816
- Last 24h
- —
- Trending rank
- —
- Security
- Not audited
Install
Works with every agent the skills CLI supports.
npx skills add https://github.com/neo4j-contrib/neo4j-skills --skill neo4j-graphql-skill- 01
Install
Run the command in your project. The CLI asks which agents to install for.
- 02
Describe the task
Ask your agent for something this skill covers. It loads neo4j-graphql-skill automatically when relevant.
- 03
Review the result
The agent follows the SKILL.md steps, scripts and references bundled with the skill.
SKILL.md
The instructions your agent reads when the skill is triggered.
When to Use
- Creating a GraphQL API from a Neo4j graph schema with
@neo4j/graphql - Writing type definitions with
@relationship,@cypher,@authorizationdirectives - Using OGM for server-side programmatic Neo4j access (bypasses GraphQL auth)
- Configuring auto-generated queries, mutations, subscriptions
- Securing types/fields with JWT or JWKS-based
@authorizationrules - Migrating from v5/v6 to v7 (breaking changes below)
When NOT to Use
- Raw Cypher queries outside GraphQL resolvers →
neo4j-cypher-skill - Spring Data Neo4j / Java entity mapping →
neo4j-spring-data-skill - Generic GraphQL without Neo4j — outside scope
Version Matrix
| Version | Status | Notes |
|---|---|---|
| v7 | Current — use ≥ 7.6.2 | @node required; options removed; explicit eq syntax |
| v5 | LTS — use ≥ 5.12.15 | Older syntax; options: {limit, offset, sort} still valid |
Default to v7 unless codebase is on v5. Upgrade past these security patches before shipping auth:
| Fix | Fixed in |
|---|---|
Subscriptions accepted an unverified JWT from WebSocket connectionParams (auth/authz bypass) | 7.5.6 / 5.12.14 |
Field-level @authentication on a root custom-resolver field ignored when the operation type also had type-level @authentication (privilege escalation) | 7.6.0 / 5.12.15 |
@authorization rules not applied on create-relationship operations | 7.6.2 |
Step 1 — Install
npm install @neo4j/graphql neo4j-driver graphql @apollo/server
For subscriptions (CDC required):
npm install ws graphql-ws express body-parser cors
Step 2 — Minimal Server Setup
import { ApolloServer } from '@apollo/server';
import { startStandaloneServer } from '@apollo/server/standalone';
import { Neo4jGraphQL } from '@neo4j/graphql';
import neo4j from 'neo4j-driver';
const typeDefs = `#graphql
type Movie @node {
id: ID! @id
title: String!
actors: [Person!]! @relationship(type: "ACTED_IN", direction: IN)
}
type Person @node {
id: ID! @id
name: String!
movies: [Movie!]! @relationship(type: "ACTED_IN", direction: OUT)
}
`;
const driver = neo4j.driver(
process.env.NEO4J_URI,
neo4j.auth.basic(process.env.NEO4J_USERNAME, process.env.NEO4J_PASSWORD)
);
const neoSchema = new Neo4jGraphQL({ typeDefs, driver });
// assertIndexesAndConstraints syncs @id → UNIQUE constraints; wrap in try/catch
await neoSchema.assertIndexesAndConstraints({ options: { create: true } });
const server = new ApolloServer({ schema: await neoSchema.getSchema() });
const { url } = await startStandaloneServer(server, {
context: async ({ req }) => ({ token: req.headers.authorization }),
listen: { port: 4000 },
});
Key Directives
@node (v7 required)
type Product @node {
id: ID! @id
name: String!
}
# Custom label (default = type name)
type Article @node(labels: ["Post", "Content"]) {
title: String!
}
@relationship — Full Syntax
type Person @node {
# direction: OUT = (this)-[:KNOWS]->(other)
friends: [Person!]! @relationship(type: "KNOWS", direction: OUT)
# direction: IN = (other)-[:ACTED_IN]->(this)
actedIn: [Movie!]! @relationship(type: "ACTED_IN", direction: IN)
# direction: UNDIRECTED = matches both directions (use sparingly — double-counts)
colleagues: [Person!]! @relationship(type: "COLLEAGUE_OF", direction: UNDIRECTED)
# Relationship with properties — reference an @relationshipProperties interface
reviews: [Movie!]! @relationship(type: "REVIEWED", direction: OUT, properties: "ReviewedProps")
}
interface ReviewedProps @relationshipProperties {
rating: Int!
date: Date
}
Querying Relationship Properties — Connection API
For each relationship with properties:, a {field}Connection field is auto-generated. Access rel properties via actorsConnection.edges.properties, not via actors:
query {
movies(where: { title: { eq: "The Matrix" } }) {
title
actorsConnection {
edges {
properties { role } # maps to @relationshipProperties interface
node { name }
}
}
}
}
@cypher — Custom Resolver
type Person @node {
name: String!
# columnName must exactly match the RETURN alias — mismatch returns null silently
friendCount: Int
@cypher(
statement: "MATCH (this)-[:KNOWS]->(f:Person) RETURN count(f) AS friendCount"
columnName: "friendCount"
)
recommendedMovies: [Movie!]!
@cypher(
statement: """
MATCH (this)-[:WATCHED]->(m:Movie)<-[:WATCHED]-(o:Person)-[:WATCHED]->(rec:Movie)
WHERE NOT (this)-[:WATCHED]->(rec)
RETURN rec
"""
columnName: "rec"
)
}
# @cypher on Query field — custom top-level query
type Query {
topRatedMovies(limit: Int = 10): [Movie!]!
@cypher(
statement: "MATCH (m:Movie) WHERE m.rating IS NOT NULL RETURN m ORDER BY m.rating DESC LIMIT $limit"
columnName: "m"
)
}
this refers to the current node in field-level @cypher. Parameters are passed as $paramName.
@cypher — Field Arguments and extend type
# extend type adds computed fields without modifying the base type definition
extend type Movie @node {
avgRating: Float
@cypher(statement: "MATCH (this)<-[r:RATED]-(:User) RETURN avg(r.rating) AS result", columnName: "result")
# Field arguments passed as Cypher params; always provide default to avoid null
recommended(limit: Int = 3): [Movie!]!
@cypher(
statement: "MATCH (this)<-[:RATED]-(u:User)-[:RATED]->(rec:Movie) WITH rec, COUNT(u) AS score ORDER BY score DESC RETURN rec LIMIT $limit"
columnName: "rec"
)
}
@id and @timestamp
type Post @node {
id: ID! @id # auto-generates UUID; creates UNIQUE constraint
createdAt: DateTime! @timestamp(operations: [CREATE])
updatedAt: DateTime @timestamp(operations: [CREATE, UPDATE])
title: String!
}
@alias — Map GraphQL field to Neo4j property
type User @node {
id: ID! @id
email: String! @alias(property: "emailAddress") # GraphQL: email → DB: emailAddress
}
@fulltext and @vector
Index must exist in Cypher before use. Phrase-capable @vector indexes accept maxPhraseLength [7.6.0] to cap embedding cost. A provider without matching features.vector config fails at schema build [7.6.1]. Full syntax, generated query shapes, provider config: references/search-directives.md.
Security — @authentication and @authorization
Step 1: Configure JWT in constructor
// Symmetric secret
const neoSchema = new Neo4jGraphQL({
typeDefs,
driver,
features: {
authorization: { key: process.env.JWT_SECRET },
},
});
// JWKS endpoint (production)
const neoSchema = new Neo4jGraphQL({
typeDefs,
driver,
features: {
authorization: {
key: { url: 'https://myapp.com/.well-known/jwks.json' },
},
},
});
Step 2: Pass token in context
context: async ({ req }) => ({ token: req.headers.authorization }),
// Or pass pre-decoded JWT:
context: async ({ req }) => ({ jwt: myDecodeJwt(req.headers.authorization) }),
Step 3: Apply @authentication and @authorization
# Require auth on all operations for a type
type Post @node
@authentication
@authorization(filter: [{ where: { node: { author: { id: { eq: "$jwt.sub" } } } } }]) {
title: String!
author: User! @relationship(type: "AUTHORED", direction: IN)
}
# requireAuthentication: false = allow public access without JWT
type Article @node
@authorization(filter: [
{ requireAuthentication: false, where: { node: { published: { eq: true } } } }
{ where: { node: { author: { id: { eq: "$jwt.sub" } } } } }
]) {
title: String!
published: Boolean!
}
# validate (throws error) vs filter (silently hides data)
type BankAccount @node
@authorization(validate: [{
when: [BEFORE],
where: { node: { owner: { id: { eq: "$jwt.sub" } } } }
}]) {
balance: Float!
}
# Role-based with custom JWT claims
type JWT @jwt {
roles: [String!]! @jwtClaim(path: "myApp.roles")
}
type AdminReport @node
@authentication(operations: [READ], jwt: { roles: { includes: "admin" } }) {
data: String!
}
BEFORE vs AFTER: CREATE supports only AFTER; READ supports only BEFORE.
Auto-Generated Operations
| Operation | Generated Name | Example |
|---|---|---|
| Query all | {plural} | movies(where, sort, limit, offset) |
| Cursor pagination | {plural}Connection | moviesConnection(first, after, where, sort) |
| Create | create{Plural} | createMovies(input: [MovieCreateInput!]!) |
| Update | update{Plural} | updateMovies(where, update) |
| Delete | delete{Plural} | deleteMovies(where, delete) |
v7 Filter Syntax (explicit eq)
# v7: explicit eq required
query {
movies(where: { title: { eq: "The Matrix" } }) {
title
actors { name }
}
}
# Sort and paginate (v7: direct args, not options wrapper)
query {
movies(sort: [{ title: ASC }], limit: 10, offset: 0) {
title
}
}
Nested Mutations
mutation {
createMovies(input: [{
title: "Inception"
actors: {
create: [{ node: { name: "Leonardo DiCaprio" } }]
connect: { where: { node: { name: { eq: "Joseph Gordon-Levitt" } } } }
}
}]) {
movies { id title }
}
}
OGM — Programmatic Access
OGM bypasses GraphQL authorization — use only in trusted server-side contexts.
import { OGM } from '@neo4j/graphql-ogm';
const ogm = new OGM({ typeDefs, driver });
await ogm.init(); // must await before using models
const Movie = ogm.model('Movie');
// find
const movies = await Movie.find({
where: { title: { eq: 'The Matrix' } },
selectionSet: `{ id title actors { name } }`,
});
// create
const { movies: created } = await Movie.create({
input: [{ title: 'Dune', actors: { create: [{ node: { name: 'Timothée Chalamet' } }] } }],
});
// update
await Movie.update({
where: { id: { eq: movieId } },
update: { title: { set: 'Dune: Part One' } },
});
// delete
await Movie.delete({ where: { id: { eq: movieId } } });
Install separately: npm install @neo4j/graphql-ogm
Subscriptions (CDC Required)
Requires Neo4j CDC enabled in FULL mode. See CDC docs.
const neoSchema = new Neo4jGraphQL({
typeDefs,
driver,
features: { subscriptions: true },
});
Authenticate subscriptions with a verified token in the WebSocket context; a pre-decoded jwt is trusted only when set server-side (7.5.6 / 5.12.14 stopped trusting client-supplied connectionParams JWTs).
subscription {
movieCreated(where: { title: { eq: "The Matrix" } }) {
createdMovie { title }
}
}
# Also: movieUpdated, movieDeleted
Schema Control Directives
type ReadOnlyData @node @mutation(operations: []) { value: String! } # disable mutations
type HeavyDoc @node {
id: ID! @id
content: String! @filterable(byValue: false) @sortable(enabled: false) # perf guard
title: String!
}
type Series @node @plural(value: "seriesList") { title: String! } # irregular plural fix
Common Errors
| Error | Cause | Fix |
|---|---|---|
Type 'X' not found | Missing @node on type (v7) | Add @node to every node type |
@cypher field returns null | columnName mismatch with RETURN alias | Match columnName exactly to RETURN alias |
| Relationship direction mismatch | Both sides declare same direction | Inverse: if A has direction: OUT, B must have direction: IN |
assertIndexesAndConstraints throws | @id constraint not in DB | Add { options: { create: true } } or run CREATE CONSTRAINT manually |
| Auth not applied | JWT not in context | Pass token: req.headers.authorization in context function |
| 0 results with valid data | v7 filter missing eq | Use { field: { eq: value } } not { field: value } |
connectOrCreate not found | Removed in v7 | Use connect + create separately |
| Memory errors on large mutations | Complex Cypher generation | Batch mutations; increase server.memory.heap.max_size |
@subscription not generating | v7 requires explicit enable | Add features: { subscriptions: true } to constructor |
v6 → v7 Breaking Changes Summary
| v6 | v7 |
|---|---|
@node optional | @node required on every node type |
options: { limit, sort } | limit, sort as direct args |
{ field: value } filter | { field: { eq: value } } |
connectOrCreate nested mutation | Removed — use connect + create |
directed arg on queries | queryDirection in @relationship |
Single rel fields actor: Person | Must use list actors: [Person!]! |
@private directive | Removed |
@unique directive | Removed |
References
- Neo4j GraphQL Docs — full directive reference, migration guides
- GraphAcademy: GraphQL Basics — hands-on course
- GitHub: @neo4j/graphql — changelog, issues
- CDC Setup — required for subscriptions
- references/search-directives.md —
@fulltext,@vector,maxPhraseLength
Checklist
-
@nodeon every GraphQL type representing a Neo4j node (v7 hard requirement) -
@idon identity fields (triggersCREATE CONSTRAINTviaassertIndexesAndConstraints) -
assertIndexesAndConstraintscalled on startup with try/catch -
@relationshipdirection correct:OUT= arrow leaves this node,IN= arrow enters - Both sides of relationship declared with inverse directions
-
@cyphercolumnNamematches RETURN alias exactly - JWT secret or JWKS URL in
features.authorization.key; token passed in context -
@authorizationfilter vs validate chosen deliberately (silent hide vs thrown error) - v7: filters use explicit
{ field: { eq: value } }syntax - v7:
limit/sortpassed as direct query args (notoptionswrapper) - OGM:
await ogm.init()called before anyogm.model()usage - Subscriptions: CDC enabled in FULL mode before enabling
features.subscriptions -
@neo4j/graphql≥ 7.6.2 (v7) or ≥ 5.12.15 (LTS) — earlier versions have auth bypasses -
.envholds credentials;.envin.gitignore
FAQ
What does the neo4j-graphql-skill skill do?
Build and configure a GraphQL API backed by Neo4j using @neo4j/graphql v7 (current) or v5 (LTS). Covers Neo4jGraphQL constructor, getSchema(), assertIndexesAndConstraints(), type definitions with @node, @relationship (IN/OUT/UNDIRECTED), @cypher for custom resolvers, @authorization/@authentication for JWT/JWKS security, auto-generated queries/mutations, OGM programmatic access, subscriptions via CDC, and Apollo Federation. Use when writing typeDefs, securing fields, or wiring Neo4j to Apollo Server. Does NOT handle raw Cypher outside resolvers — use neo4j-cypher-skill. Does NOT cover Spring Data Neo4j entity mapping — use neo4j-spring-data-skill.
How do I install neo4j-graphql-skill?
Run npx skills add https://github.com/neo4j-contrib/neo4j-skills --skill neo4j-graphql-skill in your project. The skills CLI detects the agents you use and copies the skill into the right folder. For Claude Code you can also place the skill folder at ~/.claude/skills/neo4j-graphql-skill/ (personal) or .claude/skills/neo4j-graphql-skill/ (project).
Which AI agents can use neo4j-graphql-skill?
Any agent that supports the open Agent Skills format (a folder with a SKILL.md file), including Claude Code, Codex, Cursor, GitHub Copilot, Gemini CLI, Windsurf, Cline, OpenCode and more.
Is neo4j-graphql-skill safe to install?
No partner security audit is available yet. Skills can run commands and scripts, so read the SKILL.md and any bundled files before installing.
Who maintains neo4j-graphql-skill?
It is published by neo4j-contrib in neo4j-contrib/neo4j-skills. It has 816 recorded installs.
More from neo4j-contrib/neo4j-skills
neo4j-cypher-skill
neo4j-contrib/neo4j-skills
Generates, optimizes, and validates Cypher 25 queries for Neo4j 2025.x and 2026.x. Use when writing new Cypher queries, optimizing slow queries, graph pattern matching, vector or fulltext search, subqueries, or batch writes. Covers MATCH, MERGE, CREATE, WITH, RETURN, CALL, UNWIND, FOREACH, LOAD CSV, SEARCH, expressions, functions, indexes, and subqueries. Does NOT handle driver migration or API changes — use neo4j-migration-skill. Does NOT cover DB administration or server ops — use neo4j-cli-tools-skill.
neo4j-modeling-skill
neo4j-contrib/neo4j-skills
Design, review, and refactor Neo4j graph data models. Use when choosing node labels vs relationship types vs properties, migrating relational/document schemas to graph, detecting anti-patterns (generic labels, supernodes, missing constraints), designing intermediate nodes for n-ary relationships, enforcing schema with constraints and indexes, or assessing an existing model against graph modeling best practices. Does NOT handle Cypher query authoring — use neo4j-cypher-skill. Does NOT handle Spring Data Neo4j entity mapping — use neo4j-spring-data-skill. Does NOT handle GraphQL type definitions — use neo4j-graphql-skill. Does NOT handle data import — use neo4j-import-skill.
neo4j-graphrag-skill
neo4j-contrib/neo4j-skills
Build GraphRAG retrieval pipelines on Neo4j using the neo4j-graphrag Python package (v1.22.0+). Covers retriever selection (VectorRetriever, HybridRetriever, VectorCypherRetriever, HybridCypherRetriever, Text2CypherRetriever, ToolsRetriever), external vector DB retrievers (Weaviate, Pinecone, Qdrant), retrievalquery Cypher fragments, queryparams, filters, GraphRAG pipeline wiring (GraphRAG + LLM + prompt), all LLM providers (OpenAI, Anthropic, Gemini/VertexAI, Bedrock, Cohere, Mistral, Ollama), embedder setup, index creation, token usage tracking, Cypher 25 SEARCH clause, and LangChain/LlamaIndex integration. Does NOT handle KG construction — use neo4j-document-import-skill. Does NOT handle plain vector search — use neo4j-vector-index-skill. Does NOT handle GDS analytics — use neo4j-gds-skill. Does NOT handle agent memory — use neo4j-agent-memory-skill.
neo4j-driver-python-skill
neo4j-contrib/neo4j-skills
Neo4j Python Driver v6 — driver lifecycle, executequery, managed and explicit transactions, async (AsyncGraphDatabase), result handling, data type mapping, error handling, UNWIND batching, connection pool tuning, and causal consistency. Use when writing Python code that connects to Neo4j via GraphDatabase.driver, executequery, executeread, executewrite, AsyncGraphDatabase, neo4j.Result, or RoutingControl. Package name is neo4j (not neo4j-driver) since v6. Python =3.10 required. Does NOT handle Cypher query authoring — use neo4j-cypher-skill. Does NOT cover driver upgrades or breaking changes — use neo4j-migration-skill. Does NOT cover GraphRAG pipelines (neo4j-graphrag package) — use neo4j-graphrag-skill.
neo4j-document-import-skill
neo4j-contrib/neo4j-skills
Ingests unstructured and semi-structured documents into Neo4j as a knowledge graph. Use when chunking PDFs, HTML, plain text, or Markdown; extracting entities and relationships from text with an LLM (SimpleKGPipeline, neo4j-graphrag); loading JSON via apoc.load.json; building Document→Chunk→Entity graph structures; or connecting LangChain/LlamaIndex document loaders to Neo4j. Covers neo4j-graphrag SimpleKGPipeline, LLM Graph Builder web UI, entity resolution, chunking strategies, and graph schema design for RAG pipelines. Does NOT handle structured CSV/relational import — use neo4j-import-skill. Does NOT handle GraphRAG retrieval after ingestion — use neo4j-graphrag-skill. Does NOT handle vector index creation — use neo4j-vector-search-skill.
neo4j-query-tuning-skill
neo4j-contrib/neo4j-skills
Diagnoses and fixes slow Neo4j Cypher queries by reading execution plans, identifying bad operators (AllNodesScan, CartesianProduct, Eager, NodeByLabelScan), and prescribing fixes (indexes, hints, query rewrites, runtime selection). Use when a query is slow, when EXPLAIN or PROFILE output needs interpretation, when dbHits or pageCacheHitRatio are poor, when cardinality estimation diverges from actuals, or when deciding between slotted/pipelined/parallel runtimes. Covers USING INDEX / USING SCAN / USING JOIN hints, db.stats.retrieve, SHOW QUERIES, SHOW TRANSACTIONS, TERMINATE TRANSACTION. Does NOT write new Cypher from scratch — use neo4j-cypher-skill. Does NOT cover GDS algorithm tuning — use neo4j-gds-skill. Does NOT cover index/constraint creation syntax details — use neo4j-cypher-skill references/indexes.md.
Popular backend & apis skills
find-skills
vercel-labs/skills
Helps users discover and install agent skills when they ask questions like "how do I do X", "find a skill for X", "is there a skill that can...", or express interest in extending capabilities. This skill should be used when the user is looking for functionality that might exist as an installable skill.
entra-app-registration
microsoft/azure-skills
Guides Microsoft Entra ID app registration, OAuth 2.0 authentication, and MSAL integration. USE FOR: create app registration, register Azure AD app, configure OAuth, set up authentication, add API permissions, generate service principal, MSAL example, console app auth, Entra ID setup, Azure AD authentication. DO NOT USE FOR: Key Vault secrets (use azure-keyvault-expiration-audit), general Azure resource security guidance.
google-agents-cli-adk-code
google/agents-cli
This skill should be used when the user wants to "write agent code", "build an agent with ADK", "add a tool", "create a callback", "define an agent", "use state management" — in a project that needs ADK (Agent Development Kit) API patterns and code examples. It provides a quick reference for agent types, tool definitions, orchestration patterns, callbacks, state management, the graph Workflow API, and reference recipes to study. Do NOT use for scaffolding (use google-agents-cli-scaffold) or deployment (use google-agents-cli-deploy).
embedded-captions
heygen-com/hyperframes
Add captions or subtitles to an existing single-subject talking-head video without editing the footage. Use for plain verbatim captions, cinematic captions embedded behind the subject, VFX captions, “炸/特效/酷炫字幕,” or a named identity from the 35-style catalog. Route by visual identity, not by backend engine. The quiet anchor rail is the default; embed every word only when the user explicitly wants a fully cinematic treatment. The workflow runs locally end to end, including transcription and subject matting; split multi-shot footage before applying it.
entra-agent-id
microsoft/azure-skills
Provision Microsoft Entra Agent Identity Blueprints, BlueprintPrincipals, and per-instance Agent Identities via Microsoft Graph, and configure OAuth 2.0 token exchange (fmipath, OBO, cross-tenant) including the Microsoft Entra SDK for AgentID sidecar. USE FOR: Agent Identity Blueprint, BlueprintPrincipal, agent OAuth, fmipath token exchange, agent OBO, Workload Identity Federation for agents, polyglot agent auth, Microsoft.Identity.Web.AgentIdentities. DO NOT USE FOR: standard Entra app registration (use entra-app-registration), Microsoft Foundry agent authoring (use microsoft-foundry).
neon
neondatabase/agent-skills
Overview of Neon, a complete set of cloud backend primitives around Lakebase Postgres: Auth, Object Storage, Functions, the AI Gateway, and Realtime. Start here to choose Neon for undecided login, files, APIs, and LLM calls, set up the CLI or MCP server, and follow the branch-first workflow. Use when building an app or backend on Neon, or when "Neon" or "Lakebase Postgres" is mentioned. Child skill neon-postgres wins for an existing DATABASEURL, SQL, schema, inspect, or search. Child skill neon-auth wins for login, users, sessions, identity routing, and Managed Better Auth setup. Child skill neon-realtime wins for live queries in reactive apps and agents. Also use for object storage, S3, buckets, serverless functions, function triggers, cron, AI gateway, LLM calls, realtime, logs, Loki, Grafana, observability, postgres, database, backend, Claimable Neon, neon.new, or a no-signup database.