Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ Run `mcp-graphql` with the correct endpoint, it will automatically try to intros
| `HEADERS` | JSON string containing headers for requests | `{}` |
| `ALLOW_MUTATIONS` | Enable mutation operations (disabled by default) | `false` |
| `NAME` | Name of the MCP server | `mcp-graphql` |
| `SCHEMA` | Path to a local GraphQL schema file (optional) | - |
| `SCHEMA` | Path to a local GraphQL schema file or URL (optional) | - |

### Examples

Expand All @@ -36,18 +36,21 @@ ENDPOINT=http://localhost:3000/graphql ALLOW_MUTATIONS=true npx mcp-graphql

# Using a local schema file instead of introspection
ENDPOINT=http://localhost:3000/graphql SCHEMA=./schema.graphql npx mcp-graphql

# Using a schema file hosted at a URL
ENDPOINT=http://localhost:3000/graphql SCHEMA=https://example.com/schema.graphql npx mcp-graphql
```

## Resources

- **graphql-schema**: The server exposes the GraphQL schema as a resource that clients can access. This is either the local schema file or based on an introspection query.
- **graphql-schema**: The server exposes the GraphQL schema as a resource that clients can access. This is either the local schema file, a schema file hosted at a URL, or based on an introspection query.

## Available Tools

The server provides two main tools:

1. **introspect-schema**: This tool retrieves the GraphQL schema. Use this first if you don't have access to the schema as a resource.
This uses either the local schema file or an introspection query.
This uses either the local schema file, a schema file hosted at a URL, or an introspection query.

2. **query-graphql**: Execute GraphQL queries against the endpoint. By default, mutations are disabled unless `ALLOW_MUTATIONS` is set to `true`.

Expand Down
72 changes: 45 additions & 27 deletions src/helpers/introspection.ts
Original file line number Diff line number Diff line change
@@ -1,35 +1,53 @@
import { buildClientSchema, getIntrospectionQuery, printSchema } from "graphql";
import { readFile } from "node:fs/promises";
import {buildClientSchema, getIntrospectionQuery, printSchema} from "graphql";
import {readFile} from "node:fs/promises";

/**
* Introspect a GraphQL endpoint and return the schema as the GraphQL SDL
* @param endpoint - The endpoint to introspect
* @param headers - Optional headers to include in the request
* @returns The schema
*/
export async function introspectEndpoint(
endpoint: string,
headers?: Record<string, string>,
endpoint: string,
headers?: Record<string, string>,
) {
const response = await fetch(endpoint, {
method: "POST",
headers: {
"Content-Type": "application/json",
...headers,
},
body: JSON.stringify({
query: getIntrospectionQuery(),
}),
});

if (!response.ok) {
throw new Error(`GraphQL request failed: ${response.statusText}`);
}

const responseJson = await response.json();
// Transform to a schema object
const schema = buildClientSchema(responseJson.data);

// Print the schema SDL
return printSchema(schema);
const response = await fetch(endpoint, {
method: "POST",
headers: {
"Content-Type": "application/json",
...headers,
},
body: JSON.stringify({
query: getIntrospectionQuery(),
}),
});

if (!response.ok) {
throw new Error(`GraphQL request failed: ${response.statusText}`);
}

const responseJson = await response.json();
// Transform to a schema object
const schema = buildClientSchema(responseJson.data);

// Print the schema SDL
return printSchema(schema);
}

/**
* Introspect a GraphQL schema file hosted at a URL and return the schema as the GraphQL SDL
* @param url - The URL to the schema file
* @returns The schema
*/
export async function introspectSchemaFromUrl(url: string) {
const response = await fetch(url);

if (!response.ok) {
throw new Error(`Failed to fetch schema from URL: ${response.statusText}`);
}

const schema = await response.text();
return schema;
}

/**
Expand All @@ -38,6 +56,6 @@ export async function introspectEndpoint(
* @returns The schema
*/
export async function introspectLocalSchema(path: string) {
const schema = await readFile(path, "utf8");
return schema;
const schema = await readFile(path, "utf8");
return schema;
}
Loading