Skip to main content
Glama
objectSearch.ts9.82 kB
import { getPool } from '../db.js'; import { normalizeSqlObjectName } from '../utils.js'; import { ToolResult } from './types.js'; /** * Get dependencies for a database object (tables, views, stored procedures, etc.) */ export const mcp_get_dependencies = async (args: { object_name: string }): Promise<ToolResult<any[]>> => { const { object_name } = args; console.log('Executing mcp_get_dependencies with:', { object_name }); try { const pool = getPool(); const query = ` SELECT referenced_schema_name, referenced_entity_name, referenced_database_name, referenced_server_name FROM sys.sql_expression_dependencies WHERE referencing_id = OBJECT_ID(@object_name); `; const result = await pool.request() .input('object_name', object_name) .query(query); return { success: true, data: result.recordset }; } catch (error: any) { console.error(`Error in mcp_get_dependencies for object ${object_name}:`, error); return { success: false, error: error.message }; } }; /** * Search for database objects by name pattern */ export const mcp_search_objects_by_name = async (args: { pattern: string; object_types?: string[] }): Promise<ToolResult<any[]>> => { const { pattern, object_types } = args; console.log('Executing mcp_search_objects_by_name with:', args); try { const pool = getPool(); let typeFilter = ''; if (object_types && object_types.length > 0) { const validTypes = object_types.map(type => { switch(type.toLowerCase()) { case 'table': return "'U'"; case 'view': return "'V'"; case 'procedure': return "'P'"; case 'function': return "'FN', 'IF', 'TF'"; case 'trigger': return "'TR'"; default: return null; } }).filter(Boolean); if (validTypes.length > 0) { typeFilter = `AND o.type IN (${validTypes.join(', ')})`; } } const query = ` SELECT s.name AS schema_name, o.name AS object_name, o.type_desc AS object_type, SCHEMA_NAME(o.schema_id) + '.' + o.name AS full_name, o.create_date, o.modify_date FROM sys.objects o JOIN sys.schemas s ON o.schema_id = s.schema_id WHERE o.name LIKE @pattern ${typeFilter} ORDER BY s.name, o.name; `; const result = await pool.request() .input('pattern', `%${pattern}%`) .query(query); return { success: true, data: result.recordset }; } catch (error: any) { console.error(`Error in mcp_search_objects_by_name: ${error.message}`); return { success: false, error: error.message }; } }; /** * Search in object definitions */ export const mcp_search_in_definitions = async (args: { pattern: string; object_types?: string[] }): Promise<ToolResult<any[]>> => { const { pattern, object_types } = args; console.log('Executing mcp_search_in_definitions with:', args); try { const pool = getPool(); let typeFilter = ''; if (object_types && object_types.length > 0) { const validTypes = object_types.map(type => { switch(type.toLowerCase()) { case 'procedure': return "'P'"; case 'function': return "'FN', 'IF', 'TF'"; case 'view': return "'V'"; case 'trigger': return "'TR'"; default: return null; } }).filter(Boolean); if (validTypes.length > 0) { typeFilter = `AND o.type IN (${validTypes.join(', ')})`; } } const query = ` SELECT SCHEMA_NAME(o.schema_id) AS schema_name, o.name AS object_name, o.type_desc AS object_type, SCHEMA_NAME(o.schema_id) + '.' + o.name AS full_name, o.create_date, o.modify_date FROM sys.sql_modules m JOIN sys.objects o ON m.object_id = o.object_id WHERE m.definition LIKE @pattern ${typeFilter} ORDER BY schema_name, object_name; `; const result = await pool.request() .input('pattern', `%${pattern}%`) .query(query); return { success: true, data: result.recordset }; } catch (error: any) { console.error(`Error in mcp_search_in_definitions: ${error.message}`); return { success: false, error: error.message }; } }; /** * Search for objects by their type */ export const mcp_search_objects_by_type = async (args: { object_type: string }): Promise<ToolResult<any[]>> => { const { object_type } = args; console.log('Executing mcp_search_objects_by_type with:', args); try { const pool = getPool(); let sqlType: string; switch(object_type.toLowerCase()) { case 'table': sqlType = "'U'"; break; case 'view': sqlType = "'V'"; break; case 'procedure': sqlType = "'P'"; break; case 'function': sqlType = "'FN', 'IF', 'TF'"; break; case 'trigger': sqlType = "'TR'"; break; default: sqlType = "'U'"; // Default to tables } const query = ` SELECT SCHEMA_NAME(o.schema_id) AS schema_name, o.name AS object_name, o.type_desc AS object_type, SCHEMA_NAME(o.schema_id) + '.' + o.name AS full_name, o.create_date, o.modify_date FROM sys.objects o WHERE o.type IN (${sqlType}) ORDER BY schema_name, object_name; `; const result = await pool.request().query(query); return { success: true, data: result.recordset }; } catch (error: any) { console.error(`Error in mcp_search_objects_by_type: ${error.message}`); return { success: false, error: error.message }; } }; /** * Get detailed object dependencies */ export const mcp_get_object_dependencies = async (args: { object_name: string }): Promise<ToolResult<any[]>> => { const { object_name } = args; console.log('Executing mcp_get_object_dependencies with:', args); const normalizedName = normalizeSqlObjectName(object_name); try { const pool = getPool(); // Check if the object exists const objectCheckQuery = ` SELECT object_id, type FROM sys.objects WHERE object_id = OBJECT_ID(@object_name); `; const objectCheck = await pool.request() .input('object_name', normalizedName) .query(objectCheckQuery); if (objectCheck.recordset.length === 0) { return { success: false, error: `Object ${object_name} not found` }; } const objType = objectCheck.recordset[0].type; // Get objects that this object depends on const dependsOnQuery = ` SELECT DISTINCT ISNULL(dep.referenced_schema_name, 'dbo') AS schema_name, dep.referenced_entity_name AS object_name, o.type_desc AS object_type, 'depends_on' AS relationship_type FROM sys.dm_sql_referenced_entities(@object_name, 'OBJECT') dep LEFT JOIN sys.objects o ON OBJECT_ID(ISNULL(dep.referenced_schema_name + '.', '') + dep.referenced_entity_name) = o.object_id WHERE dep.referenced_id IS NOT NULL UNION ALL SELECT DISTINCT SCHEMA_NAME(o.schema_id) AS schema_name, o.name AS object_name, o.type_desc AS object_type, 'referenced_by' AS relationship_type FROM sys.dm_sql_referencing_entities(@object_name, 'OBJECT') ref JOIN sys.objects o ON ref.referencing_id = o.object_id `; const result = await pool.request() .input('object_name', normalizedName) .query(dependsOnQuery); return { success: true, data: result.recordset }; } catch (error: any) { console.error(`Error in mcp_get_object_dependencies: ${error.message}`); return { success: false, error: error.message }; } }; /** * Comprehensive search for database objects */ export const mcp_search_comprehensive = async (args: { pattern: string; search_in_names?: boolean; search_in_definitions?: boolean; object_types?: string[] }): Promise<ToolResult<{ name_matches: any[]; definition_matches: any[]; total_matches: number; }>> => { const { pattern, search_in_names = true, search_in_definitions = true, object_types } = args; console.log('Executing mcp_search_comprehensive with:', args); try { const promises = []; // Search in object names if (search_in_names) { promises.push(mcp_search_objects_by_name({ pattern, object_types })); } else { // Return empty result with the expected structure promises.push(Promise.resolve({ success: true as const, data: [] })); } // Search in object definitions if (search_in_definitions) { promises.push(mcp_search_in_definitions({ pattern, object_types })); } else { // Return empty result with the expected structure promises.push(Promise.resolve({ success: true as const, data: [] })); } const [nameResults, definitionResults] = await Promise.all(promises); if (!nameResults.success) return nameResults; if (!definitionResults.success) return definitionResults; const nameMatches = nameResults.data; const definitionMatches = definitionResults.data; return { success: true, data: { name_matches: nameMatches, definition_matches: definitionMatches, total_matches: nameMatches.length + definitionMatches.length } }; } catch (error: any) { console.error(`Error in mcp_search_comprehensive: ${error.message}`); return { success: false, error: error.message }; } };

Implementation Reference

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/hendrickcastro/MCPQL'

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