Build Your First MCP Server with TypeScript & Gemini API: Step-by-Step Guide
Building Your First MCP Server with TypeScript (feat. Gemini API!)
Let's walk through creating a basic Model Context Protocol (MCP) server locally using TypeScript. MCP is a standard way for Large Language Models (LLMs) to interact with external tools and data. We'll build a server with a simple calculator tool and another tool that calls the Google Gemini API.
For more background on MCP, check out my previous post explaining the protocol:
what-is-mcp-a-beginner-friendly-guide-to-the-ai-communication-protocol
✅ Prerequisites
Node.js (LTS recommended)
Google Gemini API Key → Get one at Google AI Studio
✅ Step 1: Project Setup
# Create a new folder mkdir my-mcp-gemini-server
Move into it
cd my-mcp-gemini-server
Initialize npm project
npm init -y
✅ Step 2: Install Dependencies
### Install core libraries npm install @modelcontextprotocol/sdk zod @google/generative-ai dotenv ### Install dev tools npm install -D typescript @types/node
✅ Step 3: Configure TypeScript
Create a tsconfig.json file in your project root:
{ "compilerOptions": { "target": "ES2020", "module": "ESNext", "moduleResolution": "Node", "outDir": "./dist", "rootDir": "./src", "strict": true, "esModuleInterop": true, "skipLibCheck": true, "forceConsistentCasingInFileNames": true }, "include": ["src"] }
✅ Step 4: Prepare Code Files
# Create source directory mkdir src # Create main TypeScript file touch src/index.ts # Create .env file touch .env Inside .env: env GEMINI_API_KEY=YOUR_ACTUAL_GEMINI_API_KEY
🚨 Don't forget to add .env to .gitignore!
✅ Step 5: Write the MCP Server Code
Paste the following into src/index.ts:
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; import { z } from "zod"; import dotenv from 'dotenv'; import { GoogleGenerativeAI } from "@google/generative-ai"; dotenv.config(); const genAI = new GoogleGenerativeAI(process.env.GEMINI_API_KEY || ""); if (!process.env.GEMINI_API_KEY) { console.warn("⚠️ WARNING: GEMINI_API_KEY not set in .env file."); } const geminiModel = genAI.getGenerativeModel({ model: "gemini-2.0-flash" }); const server = new McpServer({ name: "MyGeminiHelper", version: "1.0.0", }); // Tool: Add server.tool( "add", { a: z.number(), b: z.number() }, async ({ a, b }) => { const result = a + b; process.stderr.write(`🛠️ Tool 'add' called: ${a} + ${b} = ${result}\n`); return { content: [{ type: "text", text: String(result) }] }; } ); // Tool: askGemini server.tool( "askGemini", { prompt: z.string() }, async ({ prompt }) => { process.stderr.write(`🤖 Tool 'askGemini' called with prompt: "${prompt}"\n`); try { const result = await geminiModel.generateContent(prompt); const response = await result.response; const text = response.text(); process.stderr.write(`✅ Gemini response received.\n`); return { content: [{ type: "text", text: text }] }; } catch (error) { process.stderr.write(`❌ Gemini API Error: ${error}\n`); return { content: [{ type: "text", text: `Error: ${error.message}` }] }; } } ); const transport = new StdioServerTransport(); console.log("🚀 Starting MCP server..."); await server.connect(transport); console.log("✅ Server connected and listening for requests!");
✅ Step 6: Compile and Run (Handle ESM Issues)
Compile TypeScript
npx tsc
Fix import error
In your package.json, add this line:
"type": "module",
Final package.json should look something like:
{ "name": "my-mcp-gemini-server", "version": "1.0.0", "type": "module", ... }
Run the server
node dist/index.js
You should see:
🚀 Starting MCP server... ✅ Server connected and listening for requests!
✅ Step 7: Test Your Server
Test the add tool:
Paste this into the terminal:
{"jsonrpc":"2.0","id":"test-add-1","method":"tools/call","params":{"name":"add","arguments":{"a":7,"b":3}}}
You should see:
🛠️ Tool 'add' called: 7 + 3 = 10
Test the askGemini tool:
{"jsonrpc":"2.0","id":"test-gemini-1","method":"tools/call","params":{"name":"askGemini","arguments":{"prompt":"Explain MCP briefly"}}}
You'll see:
🤖 Tool 'askGemini' called with prompt: "Explain MCP briefly" ✅ Gemini response received.
🎉 Conclusion
You've successfully built a local MCP server using TypeScript that can execute simple logic and interact with an external API like Gemini! This server uses Stdio for communication, but the MCP SDK also supports other transports like HTTP for web-based interactions.
This is just the beginning of exploring what's possible with MCP.
If you have any questions, feel free to email me!