examples

Things to try.

Each example names the setup it needs. The commands are run against a real stack by scripts/verify-examples.mjs, and the output shown is what they returned.

query

Count the films

Connection fields return a totalCount next to the rows.

curl -s localhost:4000/graphql -H 'content-type: application/json' \
  -d '{"query": "{ moviesConnection { totalCount } }"}'
{"data":{"moviesConnection":{"totalCount":152}}}

Needs: the default stack · docs →

queryschema

Who directed the most films?

Film counts are stored on each person (and refreshed after every mutation), so this is one sorted query.

curl -s localhost:4000/graphql -H 'content-type: application/json' \
  -d '{"query": "{ people(sort: [{ directedCount: DESC }], limit: 3) { name directedCount } }"}'
{"data":{"people":[{"name":"Christopher Nolan","directedCount":8},{"name":"Steven Spielberg","directedCount":7},{"name":"Quentin Tarantino","directedCount":6}]}}

Needs: the default stack · docs →

query

Filter and nest

Filters use operators such as contains (case-sensitive), eq and gte; relationships nest.

curl -s localhost:4000/graphql -H 'content-type: application/json' \
  -d '{"query": "{ movies(where: { title: { contains: \"Matrix\" } }) { title released genres { name } } }"}'
{"data":{"movies":[{"title":"The Matrix","released":1999,"genres":[{"name":"Action"},{"name":"Sci-Fi"}]},{"title":"The Matrix Reloaded","released":2003,"genres":[{"name":"Action"},{"name":"Sci-Fi"}]}]}}

Needs: the default stack · docs →

queryagents

Read the error, fix the statement

GraphQL answers HTTP 200 with an errors array; the message says what to fix, here with a suggestion. The second command is the corrected statement. This is the loop an agent follows.

curl -s localhost:4000/graphql -H 'content-type: application/json' \
  -d '{"query": "{ movies(where: { titel: \"x\" }) { title } }"}'
curl -s localhost:4000/graphql -H 'content-type: application/json' \
  -d '{"query": "{ movies(where: { title: { eq: \"Heat\" } }) { title released } }"}'
{"errors":[{"message":"Field \"titel\" is not defined by type \"MovieWhere\". Did you mean \"title\"?","locations":[{"line":1,"column":19}],"extensions":{"code":"GRAPHQL_VALIDATION_FAILED"}}]}
{"data":{"movies":[{"title":"Heat","released":1995}]}}

Needs: the default stack · docs →

mutation

Create a film, then remove it

Writes are open on the default stack. The first statement creates a film with a connected actor; the second deletes it again. Always filter a delete.

curl -s localhost:4000/graphql -H 'content-type: application/json' \
  -d '{"query": "mutation { createMovies(input: [{ title: \"ZZ Example\", released: 2031 }]) { movies { title released } } }"}'
curl -s localhost:4000/graphql -H 'content-type: application/json' \
  -d '{"query": "mutation { deleteMovies(where: { title: { eq: \"ZZ Example\" } }) { nodesDeleted } }"}'
{"data":{"createMovies":{"movies":[{"title":"ZZ Example","released":2031}]}}}
{"data":{"deleteMovies":{"nodesDeleted":1}}}

Needs: the default stack · docs →

agentsmcp

List the MCP tools

The MCP server speaks JSON-RPC over HTTP; send both Accept types. It is stateless, so no handshake is needed.

curl -s localhost:4100/mcp -H 'content-type: application/json' -H 'accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
event: message
data: {"result":{"tools":[{"name":"get_schema","description":"Summary of the GraphQL API: root query and mutation fields with their arguments, and the object types the schema defines with their fields and descriptions. G ...

Needs: the agents setup · docs →

agentsmcpquery

Run a query through MCP

run_query returns the JSON result as text.

curl -s localhost:4100/mcp -H 'content-type: application/json' -H 'accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"run_query","arguments":{"query":"{ moviesConnection { totalCount } }"}}}'
event: message
data: {"result":{"content":[{"type":"text","text":"{\"data\":{\"moviesConnection\":{\"totalCount\":152}}}"}],"isError":false},"jsonrpc":"2.0","id":2}

Needs: the agents setup · docs →

agentsmcpmutation

Mutations are off by default

The refusal comes back as text with isError, so the agent can read it. To allow writes, start compose with AGENTS_ALLOW_MUTATIONS=true (the server sees it as ALLOW_MUTATIONS=true).

curl -s localhost:4100/mcp -H 'content-type: application/json' -H 'accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"run_mutation","arguments":{"query":"mutation { deleteMovies { nodesDeleted } }"}}}'
event: message
data: {"result":{"content":[{"type":"text","text":"Mutations are disabled. This server is read-only by default: start it with ALLOW_MUTATIONS=true to let an agent change data. See docs/guardrails.md."}],"isError":true},"jsonrpc":"2.0","id":3}

Needs: the agents setup · docs →

federationquery

One query, two sources

The gateway asks Neo4j for the film and Wikipedia (through the Wikipedia subgraph) for the summary.

curl -s localhost:4000/graphql -H 'content-type: application/json' \
  -d '{"query": "{ movies(where: { title: { eq: \"Heat\" } }) { title released wikipedia { description pageUrl } } }"}'
{"data":{"movies":[{"title":"Heat","released":1995,"wikipedia":{"description":"1995 crime drama film by Michael Mann","pageUrl":"https://en.wikipedia.org/wiki/Heat_(1995_film)"}}]}}

Needs: the federation setup and internet · docs →

federationquery

No link, no error

A person with no Wikipedia link returns null for the Wikipedia fields, with no error.

curl -s localhost:4000/graphql -H 'content-type: application/json' \
  -d '{"query": "{ people(where: { name: { eq: \"Madonna\" } }) { name wikipediaTitle wikipedia { title } } }"}'
{"data":{"people":[{"name":"Madonna","wikipediaTitle":null,"wikipedia":null}]}}

Needs: the federation setup · docs →

authmutation

An anonymous write is refused

With grandstack-auth, reads are public but writes need a token. The gateway answers before the request reaches the server.

curl -s localhost:4000/graphql -H 'content-type: application/json' \
  -d '{"query": "mutation { deleteMovies(where: { title: { eq: \"ZZ none\" } }) { nodesDeleted } }"}'
{"errors":[{"message":"Unauthenticated: log in to change data","extensions":{"code":"UNAUTHENTICATED"}}]}

Needs: the auth setup · docs →