Skip to main content
Glama

LlamaCloud MCP Server

by run-llama
#!/usr/bin/env node /** * This is a MCP server that connects to multiple managed indexes on LlamaCloud. * Each index is exposed as a separate tool. */ import { Server } from "@modelcontextprotocol/sdk/server/index.js"; import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js"; import { LlamaCloudIndex, MetadataMode } from "llamaindex"; import packageJson from "../package.json" with { type: "json" }; // Define the tool definition interface interface ToolDefinition { indexName: string; description: string; toolName?: string; similarityTopK?: number; } // Parse command line arguments function parseToolDefinitions(): ToolDefinition[] { const args = process.argv.slice(2); if (args.length === 0) { console.error( 'No tool definitions provided. Use format: --index "IndexName" --description "Description" [--topK N]', ); process.exit(1); } const toolDefinitions: ToolDefinition[] = []; let currentTool: Partial<ToolDefinition> = {}; const pushCurrentTool = () => { if (Object.keys(currentTool).length > 0) { if (currentTool.indexName && currentTool.description) { currentTool.toolName = `get_information_${currentTool.indexName .toLowerCase() .replace(/[^a-z0-9]/g, "_")}`; toolDefinitions.push(currentTool as ToolDefinition); } else { console.warn( `Warning: Incomplete tool definition for index '${currentTool.indexName}'. It requires at least --index and --description. Skipping.`, ); } } }; for (let i = 0; i < args.length; i++) { const arg = args[i]; const value = args[i + 1]; if (arg === "--index") { pushCurrentTool(); currentTool = { indexName: value?.trim() }; i++; } else if (arg === "--description" && value) { currentTool.description = value.trim(); i++; } else if (arg === "--topK" && value) { const topK = parseInt(value, 10); if (!isNaN(topK)) { currentTool.similarityTopK = topK; } else { console.warn( `Warning: Invalid value for --topK: ${value}. Must be an integer.`, ); } i++; } } pushCurrentTool(); if (toolDefinitions.length === 0) { console.error( 'No valid tool definitions found. Use format: --index "IndexName" --description "Description" [--topK N]', ); process.exit(1); } return toolDefinitions; } /** * Create an MCP server with capabilities for tools */ const server = new Server( { name: "llamacloud-mcp-server", version: packageJson.version, }, { capabilities: { tools: {}, }, }, ); // Get the project name and API key from environment variables const projectName = process.env.LLAMA_CLOUD_PROJECT_NAME || "Default"; const apiKey = process.env.LLAMA_CLOUD_API_KEY || (() => { throw new Error("LLAMA_CLOUD_API_KEY is not set"); })(); // Parse tool definitions from command line arguments const toolDefinitions = parseToolDefinitions(); // Create indexes for each tool definition const indexes = new Map<string, LlamaCloudIndex>(); for (const definition of toolDefinitions) { const index = new LlamaCloudIndex({ name: definition.indexName, projectName, apiKey, }); indexes.set(definition.toolName!, index); process.stderr.write( `Created index for tool ${definition.toolName}: ${definition.indexName} - ${definition.description}\n`, ); } /** * Handler that lists available tools. * Exposes a tool for each index that lets clients retrieve information. */ server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools: toolDefinitions.map((definition) => ({ name: definition.toolName!, description: `Get information from the ${definition.indexName} index. The index contains ${definition.description}`, inputSchema: { type: "object", properties: { query: { type: "string", description: `The query used to get information from the ${definition.indexName} index.`, }, }, required: ["query"], }, })), }; }); /** * Handler for tool calls. * Routes requests to the appropriate index based on the tool name. */ server.setRequestHandler(CallToolRequestSchema, async (request) => { const toolName = request.params.name; const index = indexes.get(toolName); if (!index) { throw new Error(`Unknown tool: ${toolName}`); } const query = String(request.params.arguments?.query); if (!query) { throw new Error("query parameter is required"); } const toolDefinition = toolDefinitions.find( (def) => def.toolName === toolName, ); const retriever = index.asRetriever({ similarityTopK: toolDefinition?.similarityTopK, }); const nodesWithScore = await retriever.retrieve({ query }); const nodes = nodesWithScore.map((node) => node.node); const context = nodes.map((r) => r.getContent(MetadataMode.LLM)).join("\n\n"); return { content: [ { type: "text", text: context, }, ], }; }); /** * Start the server using stdio transport. * This allows the server to communicate via standard input/output streams. */ async function main() { process.stderr.write( `Starting MCP server with ${toolDefinitions.length} tools:\n`, ); toolDefinitions.forEach((def) => { process.stderr.write( `- ${def.toolName}: ${def.indexName} - ${def.description}\n`, ); }); const transport = new StdioServerTransport(); await server.connect(transport); } main().catch((error) => { console.error("Server error:", error); process.exit(1); });

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/run-llama/mcp-server-llamacloud'

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