Skip to main content
Glama

Terraform Registry MCP Server

by thrashr888
providerGuides.ts5.99 kB
import { ProviderGuidesInput, ResponseContent } from "../types/index.js"; import { createStandardResponse, addStandardContext } from "../utils/responseUtils.js"; import { handleToolError } from "../utils/responseUtils.js"; import { REGISTRY_API_BASE } from "../../config.js"; import logger from "../utils/logger.js"; interface GuideDoc { id: string; title: string; slug: string; description?: string; content?: string; } interface GuideDataItem { id: string; attributes: { title: string; slug: string; content?: string; }; } /** * Handles the providerGuides tool request */ export async function handleProviderGuides(params: ProviderGuidesInput): Promise<ResponseContent> { try { logger.debug("Processing providerGuides request", params); const { provider, namespace = "hashicorp", guide, search } = params; if (!provider) { throw new Error("Provider is required"); } // For testing, we'll use a known version ID that works const versionId = "67250"; // This is a recent AWS provider version // Build the URL for fetching guides const guidesUrl = `${REGISTRY_API_BASE}/v2/provider-docs?filter[provider-version]=${versionId}&filter[category]=guides&filter[language]=hcl`; logger.info("Fetching guides from:", guidesUrl); const guidesResponse = await fetch(guidesUrl); if (!guidesResponse.ok) { throw new Error(`Failed to fetch guides: ${guidesResponse.status} ${guidesResponse.statusText}`); } const guidesData = await guidesResponse.json(); if (!guidesData.data || !Array.isArray(guidesData.data)) { throw new Error("Invalid guides response format"); } // Convert guides to more usable format const guides: GuideDoc[] = guidesData.data.map((item: GuideDataItem) => ({ id: item.id, title: item.attributes.title, slug: item.attributes.slug })); // If a specific guide is requested, fetch its content if (guide) { const targetGuide = guides.find((g) => g.slug === guide || g.title.toLowerCase().includes(guide.toLowerCase())); if (!targetGuide) { throw new Error(`Guide '${guide}' not found`); } // Fetch the specific guide content const guideUrl = `${REGISTRY_API_BASE}/v2/provider-docs/${targetGuide.id}`; logger.info("Fetching guide content from:", guideUrl); const guideResponse = await fetch(guideUrl); if (!guideResponse.ok) { throw new Error(`Failed to fetch guide content: ${guideResponse.status} ${guideResponse.statusText}`); } const guideData = await guideResponse.json(); if (!guideData.data?.attributes?.content) { throw new Error("Guide content is empty or malformed"); } // Extract description from the content const descriptionMatch = guideData.data.attributes.content.match(/description: |-\n(.*?)\n---/s); const description = descriptionMatch ? descriptionMatch[1].trim() : ""; // Format the response for a single guide let markdownResponse = `# ${targetGuide.title}\n\n`; if (description) { markdownResponse += `${description}\n\n`; } markdownResponse += `${guideData.data.attributes.content.split("---")[2]?.trim() || ""}\n\n`; const metadata = { provider, namespace, guide: { title: targetGuide.title, slug: targetGuide.slug, id: targetGuide.id } }; addStandardContext(metadata); return createStandardResponse("success", markdownResponse, metadata); } // If search is provided, filter guides let filteredGuides = guides; if (search) { const searchLower = search.toLowerCase(); filteredGuides = guides.filter( (guide) => guide.title.toLowerCase().includes(searchLower) || guide.slug.toLowerCase().includes(searchLower) ); } // Format the response for guide listing const sections = [ { title: "Available Guides", guides: filteredGuides.map((guide) => ({ title: guide.title, slug: guide.slug })) } ]; // Group guides by type if we can identify patterns const upgradeGuides = filteredGuides.filter((g) => g.slug.includes("version-") && g.slug.includes("-upgrade")); const featureGuides = filteredGuides.filter((g) => !g.slug.includes("version-") || !g.slug.includes("-upgrade")); if (upgradeGuides.length > 0) { sections.push({ title: "Version Upgrade Guides", guides: upgradeGuides }); } if (featureGuides.length > 0) { sections.push({ title: "Feature & Integration Guides", guides: featureGuides }); } let markdownResponse = `# ${namespace}/${provider} Provider Guides\n\n`; if (search) { markdownResponse += `Search results for: "${search}"\n\n`; } if (filteredGuides.length === 0) { markdownResponse += "No guides found.\n\n"; } else { sections.forEach((section) => { if (section.guides.length > 0) { markdownResponse += `## ${section.title}\n\n`; section.guides.forEach((guide) => { markdownResponse += `- [${guide.title}](${REGISTRY_API_BASE}/providers/${namespace}/${provider}/latest/docs/guides/${guide.slug})\n`; }); markdownResponse += "\n"; } }); } const metadata = { provider, namespace, summary: { total: filteredGuides.length, upgradeGuides: upgradeGuides.length, featureGuides: featureGuides.length } }; addStandardContext(metadata); return createStandardResponse("success", markdownResponse, metadata); } catch (error) { return handleToolError("providerGuides", error, { inputParams: params, context: { message: error instanceof Error ? error.message : "Unknown error occurred", timestamp: new Date().toISOString() } }); } }

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/thrashr888/terraform-mcp-server'

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