introspect-schema
Analyze GraphQL schema structure to understand available queries, types, and directives. Filter by specific types to focus on relevant schema components for development and debugging.
Instructions
Introspect the GraphQL schema. Optionally filter to specific types.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| descriptions | No | ||
| directives | No | ||
| typeNames | No | e.g., ["Query", "User"] |
Implementation Reference
- src/index.ts:94-121 (handler)The main handler function for the 'introspect-schema' tool. It handles introspection of the full schema or specific types using imported helper functions.const introspectSchemaHandler = async ({ typeNames, descriptions = true, directives = true }: any) => { if (typeNames === null) { typeNames = undefined; } try { if (typeNames && typeNames.length > 0) { const filtered = await introspectTypes(env.ENDPOINT, env.HEADERS, typeNames); return { content: [{ type: "text", text: filtered }] }; } else { let schema; if (env.SCHEMA) { if (env.SCHEMA.startsWith("http://") || env.SCHEMA.startsWith("https://")) { schema = await introspectSchemaFromUrl(env.SCHEMA); } else { schema = await introspectLocalSchema(env.SCHEMA); } } else { schema = await introspectEndpoint(env.ENDPOINT, env.HEADERS); } return { content: [{ type: "text", text: schema }] }; } } catch (error) { return { isError: true, content: [{ type: "text", text: `Introspection failed: ${error}` }], }; } };
- src/index.ts:127-131 (schema)Zod input schema for the tool parameters: typeNames (optional array of strings), descriptions and directives (optional booleans, default true).{ typeNames: z.array(z.string()).optional().describe("A list of specific type names to filter the introspection."), descriptions: z.boolean().optional().default(true), directives: z.boolean().optional().default(true), },
- src/index.ts:124-133 (registration)MCP server.tool registration that registers the 'introspect-schema' tool with its description, input schema, and handler function.server.tool( "introspect-schema", "Introspect the GraphQL schema. Optionally filter to specific types.", { typeNames: z.array(z.string()).optional().describe("A list of specific type names to filter the introspection."), descriptions: z.boolean().optional().default(true), directives: z.boolean().optional().default(true), }, introspectSchemaHandler );
- src/helpers/introspection.ts:21-46 (helper)Core helper function to introspect a GraphQL endpoint using getIntrospectionQuery, buildClientSchema, and printSchema to return the SDL.export async function introspectEndpoint( 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 as any).data); // Print the schema SDL return printSchema(schema); }
- src/helpers/introspection.ts:90-170 (helper)Helper function to introspect specific types from the schema, returning a JSON summary of their structure (fields, args, etc.). Used when typeNames are provided.export async function introspectTypes( endpoint: string, headers: Record<string, string> = {}, typeNames: string[] ) { const response = await fetch(endpoint, { method: "POST", headers: { "Content-Type": "application/json", ...headers }, body: JSON.stringify({ query: getIntrospectionQuery() }), }); const data = await response.json(); const schema = buildClientSchema(data.data); const result: Record<string, any> = {}; for (const name of typeNames) { const type = schema.getType(name); if (!type) continue; // Handle object/interface types if (isObjectLikeType(type)) { result[name] = { kind: type instanceof GraphQLObjectType ? "OBJECT" : "INTERFACE", description: type.description, fields: Object.fromEntries( Object.entries(type.getFields()).map(([fieldName, field]) => [ fieldName, { type: field.type.toString(), description: field.description, args: field.args.map(arg => ({ name: arg.name, type: arg.type.toString(), description: arg.description, })) } ]) ) }; } // Handle union types else if (isUnionType(type)) { result[name] = { kind: "UNION", description: type.description, possibleTypes: type.getTypes().map(t => t.name) }; } // Handle enums else if (isEnumType(type)) { result[name] = { kind: "ENUM", description: type.description, values: type.getValues().map(v => ({ name: v.name, description: v.description })) }; } // Handle scalars and input objects else if (isInputObjectType(type)) { result[name] = { kind: "INPUT_OBJECT", description: type.description, fields: Object.fromEntries( Object.entries(type.getFields()).map(([fieldName, field]) => [ fieldName, { type: field.type.toString(), description: field.description } ]) ) }; } else if (type instanceof GraphQLScalarType) { result[name] = { kind: "SCALAR", description: type.description }; } } return JSON.stringify(result, null, 2); }