Skip to main content
Glama

Pinecone MCP Server

by Solaceking
index.ts7.41 kB
#!/usr/bin/env node /** * Pinecone MCP Server * Provides tools for interacting with Pinecone vector database * - Query vectors with semantic search * - Upsert new vectors * - Delete vectors * - Get index statistics */ import { Server } from "@modelcontextprotocol/sdk/server/index.js"; import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js"; // @ts-ignore import { Pinecone } from "pinecone"; import OpenAI from "openai"; // Environment variables const PINECONE_API_KEY = process.env.PINECONE_API_KEY; const OPENAI_API_KEY = process.env.OPENAI_API_KEY; const INDEX_NAME = process.env.PINECONE_INDEX_NAME || "ad-assessor-docs"; if (!PINECONE_API_KEY) { throw new Error("PINECONE_API_KEY environment variable is required"); } if (!OPENAI_API_KEY) { throw new Error("OPENAI_API_KEY environment variable is required"); } // Initialize clients const pc = new Pinecone({ apiKey: PINECONE_API_KEY }); const openai = new OpenAI({ apiKey: OPENAI_API_KEY }); /** * Create an MCP server with tools for Pinecone operations */ const server = new Server( { name: "pinecone-mcp", version: "0.1.0", }, { capabilities: { tools: {}, }, } ); /** * Get embedding for text using OpenAI */ async function getEmbedding(text: string): Promise<number[]> { const response = await openai.embeddings.create({ input: text, model: "text-embedding-ada-002" }); return response.data[0].embedding; } /** * Handler that lists available tools for Pinecone operations */ server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools: [ { name: "query_vectors", description: "Perform semantic search on the Pinecone vector database", inputSchema: { type: "object", properties: { query: { type: "string", description: "Text query to search for similar content" }, top_k: { type: "number", description: "Number of results to return (default: 5)", default: 5 }, include_metadata: { type: "boolean", description: "Whether to include metadata in results (default: true)", default: true } }, required: ["query"] } }, { name: "upsert_vectors", description: "Add new vectors to the Pinecone database", inputSchema: { type: "object", properties: { texts: { type: "array", items: { type: "string" }, description: "Array of text strings to embed and store" }, metadatas: { type: "array", items: { type: "object" }, description: "Array of metadata objects for each text" }, ids: { type: "array", items: { type: "string" }, description: "Array of IDs for the vectors (optional, auto-generated if not provided)" } }, required: ["texts"] } }, { name: "delete_vectors", description: "Delete vectors from the Pinecone database", inputSchema: { type: "object", properties: { ids: { type: "array", items: { type: "string" }, description: "Array of vector IDs to delete" }, delete_all: { type: "boolean", description: "Delete all vectors in the index (use with caution)", default: false } } } }, { name: "get_index_stats", description: "Get statistics about the Pinecone index", inputSchema: { type: "object", properties: {} } } ] }; }); /** * Handler for tool calls */ server.setRequestHandler(CallToolRequestSchema, async (request) => { const index = pc.index(INDEX_NAME); switch (request.params.name) { case "query_vectors": { const query = String(request.params.arguments?.query); const topK = Number(request.params.arguments?.top_k) || 5; const includeMetadata = request.params.arguments?.include_metadata !== false; if (!query) { throw new Error("Query is required"); } // Get embedding for the query const queryEmbedding = await getEmbedding(query); // Query Pinecone const queryResponse = await index.query({ vector: queryEmbedding, topK, includeMetadata }); return { content: [{ type: "text", text: JSON.stringify(queryResponse, null, 2) }] }; } case "upsert_vectors": { const texts = request.params.arguments?.texts as string[]; const metadatas = request.params.arguments?.metadatas as object[] | undefined; const ids = request.params.arguments?.ids as string[] | undefined; if (!texts || !Array.isArray(texts) || texts.length === 0) { throw new Error("Texts array is required and must not be empty"); } // Generate embeddings for all texts const embeddings = await Promise.all(texts.map(text => getEmbedding(text))); // Prepare vectors for upsert const vectors = texts.map((text, i) => ({ id: ids?.[i] || `vec_${Date.now()}_${i}`, values: embeddings[i], metadata: { text, ...metadatas?.[i] } })); // Upsert to Pinecone const upsertResponse = await index.upsert(vectors); return { content: [{ type: "text", text: `Successfully upserted ${vectors.length} vectors. Response: ${JSON.stringify(upsertResponse)}` }] }; } case "delete_vectors": { const ids = request.params.arguments?.ids as string[] | undefined; const deleteAll = Boolean(request.params.arguments?.delete_all); if (deleteAll) { const deleteResponse = await index.deleteAll(); return { content: [{ type: "text", text: `Deleted all vectors from index. Response: ${JSON.stringify(deleteResponse)}` }] }; } if (!ids || !Array.isArray(ids) || ids.length === 0) { throw new Error("IDs array is required for selective deletion"); } const deleteResponse = await index.deleteMany(ids); return { content: [{ type: "text", text: `Deleted ${ids.length} vectors. Response: ${JSON.stringify(deleteResponse)}` }] }; } case "get_index_stats": { const stats = await index.describeIndexStats(); return { content: [{ type: "text", text: JSON.stringify(stats, null, 2) }] }; } default: throw new Error(`Unknown tool: ${request.params.name}`); } }); /** * Start the server using stdio transport */ async function main() { const transport = new StdioServerTransport(); await server.connect(transport); console.error("Pinecone MCP server running on stdio"); } 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/Solaceking/pinecone-mcp-server'

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