The Unreal Engine MCP Server now includes a GraphQL API that provides a flexible, efficient alternative to the standard MCP tools for complex queries. The GraphQL API allows you to:
- Query multiple related objects in a single request
- Specify exactly what data you need (no over-fetching)
- Use nested queries to traverse object relationships
- Perform mutations (create, update, delete) through mutations
- Leverage GraphQL's strong typing and introspection
# Enable/disable GraphQL server
GRAPHQL_ENABLED=true
# Server host and port
GRAPHQL_HOST=127.0.0.1
GRAPHQL_PORT=4000
# GraphQL endpoint path
GRAPHQL_PATH=/graphql
# CORS settings
GRAPHQL_CORS_ORIGIN=*
GRAPHQL_CORS_CREDENTIALS=falseThe GraphQL server runs on a separate port from the MCP server:
- URL:
http://127.0.0.1:4000/graphql - Default Port: 4000 (configurable via
GRAPHQL_PORT) - Default Host: 127.0.0.1 (configurable via
GRAPHQL_HOST)
- Vector: 3D vector with
x,y,zfields (Float) - Rotator: Rotation with
pitch,yaw,rollfields (Float, degrees) - Transform: Combined transform with
location,rotation,scale(Vector/Rotator/Vector) - JSON: Arbitrary JSON data
type Asset {
name: String!
path: String!
class: String!
packagePath: String!
size: Float
dependencies: [Asset!]!
dependents: [Asset!]!
metadata: JSON
tags: [String!]!
}type Actor {
name: String!
class: String!
location: Vector
rotation: Rotator
scale: Vector
components: [Component!]!
tags: [String!]!
properties: JSON
}type Blueprint {
name: String!
path: String!
parentClass: String
variables: [Variable!]!
functions: [Function!]!
events: [Event!]!
components: [Component!]!
scsHierarchy: JSON
}query {
assets {
edges {
node {
name
path
class
packagePath
}
cursor
}
pageInfo {
hasNextPage
hasPreviousPage
}
totalCount
}
}query {
assets(filter: { class: "Material" }) {
edges {
node {
name
path
class
tags
}
}
totalCount
}
}query {
asset(path: "/Game/Materials/M_Master") {
name
path
class
dependencies {
name
path
}
dependents {
name
path
}
metadata
tags
}
}query {
assets(pagination: { offset: 0, limit: 10 }) {
edges {
node {
name
path
class
}
cursor
}
pageInfo {
hasNextPage
hasPreviousPage
startCursor
endCursor
}
totalCount
}
}query {
actors {
edges {
node {
name
class
location {
x
y
z
}
rotation {
pitch
yaw
roll
}
tags
}
}
totalCount
}
}query {
actor(name: "SpotLight_Main") {
name
class
location {
x
y
z
}
rotation {
pitch
yaw
roll
}
tags
properties
components {
name
type
properties
}
}
}query {
actors(filter: { tag: "Enemy" }) {
edges {
node {
name
class
tags
}
}
totalCount
}
}query {
blueprint(path: "/Game/Blueprints/BP_PlayerCharacter") {
name
path
parentClass
variables {
name
type
defaultValue
metadata
}
functions {
name
inputs {
name
type
}
outputs {
name
type
}
}
events {
name
type
}
components {
name
type
}
scsHierarchy
}
}query {
blueprints {
edges {
node {
name
path
parentClass
variables {
name
type
}
functions {
name
}
}
}
totalCount
}
}query {
blueprints(filter: { parentClass: "Actor" }) {
edges {
node {
name
path
parentClass
}
}
totalCount
}
}query {
currentLevel {
name
path
loaded
lightingQuality
actors {
name
class
}
streamingLevels
}
}query {
levels {
name
path
loaded
actorCount
}
}query {
search(query: "Player", type: ALL) {
... on Asset {
name
path
__typename
}
... on Actor {
name
class
__typename
}
... on Blueprint {
name
path
__typename
}
}
}query {
search(query: "Material", type: ASSETS) {
... on Asset {
name
path
class
}
}
}mutation {
duplicateAsset(path: "/Game/Materials/M_Master", newName: "M_Master_Copy") {
name
path
class
}
}mutation {
moveAsset(path: "/Game/Materials/M_Master", newPath: "/Game/Archived/Materials/M_Master") {
name
path
}
}mutation {
deleteAsset(path: "/Game/Materials/M_Old")
}mutation {
spawnActor(input: {
classPath: "StaticMeshActor"
name: "Cube_001"
transform: {
location: { x: 0, y: 0, z: 100 }
rotation: { pitch: 0, yaw: 0, roll: 0 }
scale: { x: 1, y: 1, z: 1 }
}
tags: ["Spawned"]
}) {
name
class
location {
x
y
z
}
tags
}
}mutation {
deleteActor(name: "Cube_001")
}mutation {
setActorTransform(
name: "SpotLight_Main"
transform: {
location: { x: 500, y: 300, z: 200 }
rotation: { pitch: 45, yaw: 90, roll: 0 }
scale: { x: 1, y: 1, z: 1 }
}
) {
name
location {
x
y
z
}
rotation {
pitch
yaw
roll
}
}
}mutation {
createBlueprint(input: {
name: "BP_NewCharacter"
blueprintType: "Actor"
savePath: "/Game/Blueprints"
}) {
name
path
parentClass
}
}mutation {
addVariableToBlueprint(
path: "/Game/Blueprints/BP_NewCharacter"
input: {
variableName: "Health"
variableType: "Float"
defaultValue: 100
}
) {
name
variables {
name
type
defaultValue
}
}
}mutation {
addFunctionToBlueprint(
path: "/Game/Blueprints/BP_NewCharacter"
input: {
functionName: "TakeDamage"
inputs: [
{ name: "Damage", type: "Float" }
{ name: "Source", type: "String" }
]
}
) {
name
functions {
name
inputs {
name
type
}
}
}
}mutation {
loadLevel(path: "/Game/Maps/Level_01") {
name
path
loaded
actorCount
}
}mutation {
saveLevel(path: "/Game/Maps/Level_01")
}mutation {
createMaterialInstance(
parentPath: "/Game/Materials/M_Master"
name: "MI_Player"
parameters: {
BaseColor: { x: 1, y: 0, z: 0 }
Metallic: 0.5
}
) {
name
path
class
}
}Fragments allow you to reuse field selections:
fragment AssetInfo on Asset {
name
path
class
packagePath
}
query {
assets(filter: { class: "Material" }) {
edges {
node {
...AssetInfo
dependencies {
...AssetInfo
}
}
}
}
}Use variables for dynamic queries:
query GetAsset($path: String!, $withDependencies: Boolean!) {
asset(path: $path) {
...AssetInfo
dependencies @include(if: $withDependencies) {
...AssetInfo
}
}
}
fragment AssetInfo on Asset {
name
path
class
}With these variables:
{
"path": "/Game/Materials/M_Master",
"withDependencies": true
}Use aliases to rename fields in results:
query {
materials: assets(filter: { class: "Material" }) {
edges {
node {
materialName: name
materialPath: path
class
}
}
}
}Get the complete schema:
query {
__schema {
types {
name
kind
fields {
name
type {
name
kind
}
}
}
}
}Always specify only the fields you need:
# Good
query {
assets {
edges {
node {
name
path
}
}
}
}
# Bad (over-fetching)
query {
assets {
edges {
node {
_ # Get everything
}
}
}
}Create fragments for commonly used field sets:
fragment ActorBasicInfo on Actor {
name
class
location {
x
y
z
}
}Always use pagination for queries that might return many results:
query {
assets(pagination: { offset: 0, limit: 50 }) {
edges {
node {
name
path
}
}
pageInfo {
hasNextPage
hasPreviousPage
}
}
}Filter results on the server side to reduce data transfer:
query {
actors(filter: { class: "StaticMeshActor", tag: "Static" }) {
edges {
node {
name
class
}
}
}
}Use mutations instead of queries for operations that modify data:
mutation {
spawnActor(input: { ... }) {
name
location {
x
y
z
}
}
}- Unreal Connection Required: GraphQL resolvers require an active connection to Unreal Editor
- Plugin Support: Some queries require specific Unreal plugins to be enabled
- Performance: Complex nested queries may be slower than focused MCP tool calls
- Not a Replacement: GraphQL complements but doesn't replace the MCP tool system
Check logs for errors:
# Check if port is already in use
netstat -an | grep 4000
# Verify environment variables
echo $GRAPHQL_ENABLED
echo $GRAPHQL_PORTIncrease timeout in your GraphQL client, or break complex queries into smaller parts.
Currently, GraphQL API has no authentication. Access is restricted to localhost by default. For production, consider:
- Running behind a reverse proxy with authentication
- Implementing API keys
- Using VPN or firewall rules
| MCP Tool | GraphQL Query | Notes |
|---|---|---|
manage_asset (list) |
assets query |
Use filter and pagination |
manage_asset (create) |
createMaterialInstance mutation |
Asset creation varies |
control_actor (spawn) |
spawnActor mutation |
Transform input format |
control_actor (delete) |
deleteActor mutation |
Simpler API |
manage_blueprint (get) |
blueprint query |
More detailed response |
manage_level (load) |
loadLevel mutation |
Direct mapping |
Before (MCP Tool):
{
"tool": "manage_asset",
"arguments": {
"action": "list",
"directory": "/Game"
}
}After (GraphQL):
query {
assets(filter: { pathStartsWith: "/Game" }, pagination: { limit: 100 }) {
edges {
node {
name
path
class
}
}
totalCount
}
}- GraphiQL - In-browser GraphQL IDE
- Apollo Studio - Powerful visual editor
- Insomnia - REST client with GraphQL support
- Postman - API platform with GraphQL support
- Start the MCP server with
GRAPHQL_ENABLED=true - Use a GraphQL client (GraphiQL, Apollo Studio, Insomnia, or Postman) to explore the schema
- Try the query examples above
- Build your own queries tailored to your needs
- Consider using fragments and variables for complex workflows