Skip to main content
Glama

Advanced Hasura GraphQL MCP Server

by husamabusafa

describe_table

Examine table structure with column types and descriptions using a Hasura GraphQL MCP Server. Input table name and optional schema to retrieve details.

Instructions

Shows the structure of a table including all columns with their types and descriptions

Input Schema

NameRequiredDescriptionDefault
schemaNameNoOptional. The database schema name, defaults to 'public'public
tableNameYesThe exact name of the table to describe

Input Schema (JSON Schema)

{ "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "properties": { "schemaName": { "default": "public", "description": "Optional. The database schema name, defaults to 'public'", "type": "string" }, "tableName": { "description": "The exact name of the table to describe", "type": "string" } }, "required": [ "tableName" ], "type": "object" }

Implementation Reference

  • The handler function for 'describe_table' tool. It performs GraphQL introspection to fetch the table type, handles case variations for type name, parses field types (including lists and non-nulls), and returns structured column information.
    async ({ tableName, schemaName }) => { console.log(`[INFO] Executing tool 'describe_table' for table: ${tableName} in schema: ${schemaName}`); try { const schema = await getIntrospectionSchema(); const tableTypeQuery = gql` query GetTableType($typeName: String!) { __type(name: $typeName) { name kind description fields { name description type { kind name ofType { kind name ofType { kind name ofType { kind name } } } } args { name description type { kind name ofType { kind name } } } } } } `; const tableTypeResult = await makeGqlRequest(tableTypeQuery, { typeName: tableName }); if (!tableTypeResult.__type) { console.log(`[INFO] No direct match for table type: ${tableName}, trying case variations`); const pascalCaseName = tableName.charAt(0).toUpperCase() + tableName.slice(1); const alternativeResult = await makeGqlRequest(tableTypeQuery, { typeName: pascalCaseName }); if (!alternativeResult.__type) { throw new Error(`Table '${tableName}' not found in schema. Check the table name and schema.`); } tableTypeResult.__type = alternativeResult.__type; } const columnsInfo = tableTypeResult.__type.fields.map((field: any) => { let typeInfo = field.type; let typeString = ''; let isNonNull = false; let isList = false; while (typeInfo) { if (typeInfo.kind === 'NON_NULL') { isNonNull = true; typeInfo = typeInfo.ofType; } else if (typeInfo.kind === 'LIST') { isList = true; typeInfo = typeInfo.ofType; } else { typeString = typeInfo.name || 'unknown'; break; } } let fullTypeString = ''; if (isList) { fullTypeString = `[${typeString}]`; } else { fullTypeString = typeString; } if (isNonNull) { fullTypeString += '!'; } return { name: field.name, type: fullTypeString, description: field.description || null, args: field.args?.length ? field.args : null }; }); const result = { table: { name: tableName, schema: schemaName, description: tableTypeResult.__type.description || null, columns: columnsInfo.sort((a: any, b: any) => a.name.localeCompare(b.name)) } }; return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] }; } catch (error: any) { console.error(`[ERROR] Tool 'describe_table' failed: ${error.message}`); throw error; } }
  • Input schema using Zod: requires 'tableName' (string), optional 'schemaName' (string, defaults to 'public').
    { tableName: z.string().describe("The exact name of the table to describe"), schemaName: z.string().optional().default('public').describe("Optional. The database schema name, defaults to 'public'") },
  • src/index.ts:468-585 (registration)
    Registration of the 'describe_table' tool via server.tool(), including name, description, input schema, and handler reference.
    "describe_table", "Shows the structure of a table including all columns with their types and descriptions", { tableName: z.string().describe("The exact name of the table to describe"), schemaName: z.string().optional().default('public').describe("Optional. The database schema name, defaults to 'public'") }, async ({ tableName, schemaName }) => { console.log(`[INFO] Executing tool 'describe_table' for table: ${tableName} in schema: ${schemaName}`); try { const schema = await getIntrospectionSchema(); const tableTypeQuery = gql` query GetTableType($typeName: String!) { __type(name: $typeName) { name kind description fields { name description type { kind name ofType { kind name ofType { kind name ofType { kind name } } } } args { name description type { kind name ofType { kind name } } } } } } `; const tableTypeResult = await makeGqlRequest(tableTypeQuery, { typeName: tableName }); if (!tableTypeResult.__type) { console.log(`[INFO] No direct match for table type: ${tableName}, trying case variations`); const pascalCaseName = tableName.charAt(0).toUpperCase() + tableName.slice(1); const alternativeResult = await makeGqlRequest(tableTypeQuery, { typeName: pascalCaseName }); if (!alternativeResult.__type) { throw new Error(`Table '${tableName}' not found in schema. Check the table name and schema.`); } tableTypeResult.__type = alternativeResult.__type; } const columnsInfo = tableTypeResult.__type.fields.map((field: any) => { let typeInfo = field.type; let typeString = ''; let isNonNull = false; let isList = false; while (typeInfo) { if (typeInfo.kind === 'NON_NULL') { isNonNull = true; typeInfo = typeInfo.ofType; } else if (typeInfo.kind === 'LIST') { isList = true; typeInfo = typeInfo.ofType; } else { typeString = typeInfo.name || 'unknown'; break; } } let fullTypeString = ''; if (isList) { fullTypeString = `[${typeString}]`; } else { fullTypeString = typeString; } if (isNonNull) { fullTypeString += '!'; } return { name: field.name, type: fullTypeString, description: field.description || null, args: field.args?.length ? field.args : null }; }); const result = { table: { name: tableName, schema: schemaName, description: tableTypeResult.__type.description || null, columns: columnsInfo.sort((a: any, b: any) => a.name.localeCompare(b.name)) } }; return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] }; } catch (error: any) { console.error(`[ERROR] Tool 'describe_table' failed: ${error.message}`); throw error; } } );

Other Tools

Related Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/husamabusafa/hasura_mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server