MCP (Model Context Protocol) turns your codebase into a first-class citizen for AI agents. Instead of copy-pasting context, you build a server that speaks MCP, and the agent queries it like a database. Here's a 15-minute build that exposes your repository's architecture and open issues.

Step 1: Scaffold the server

We'll use the official TypeScript SDK. Run:

mkdir my-mcp-server && cd my-mcp-server
npm init -y
npm install @modelcontextprotocol/sdk zod
npm install -D typescript @types/node
npx tsc --init --module node16 --moduleResolution node16 --target es2022 --outDir dist

Create src/index.ts:

import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";

const server = new McpServer({ name: "codebase-helper", version: "1.0.0" });

Step 2: Add a "find-issue" tool

Agents need to know what to work on. Add a tool that reads GitHub issues:

server.tool(
  "get_open_issues",
  "List current open issues from the repository",
  { repo: z.string().default("your-org/your-repo") },
  async ({ repo }) => {
    const res = await fetch(`https://api.github.com/repos/${repo}/issues?state=open`);
    const issues = await res.json();
    const text = issues.slice(0, 10).map(i => `- #${i.number}: ${i.title}`).join("\n");
    return { content: [{ type: "text", text: text || "No open issues." }] };
  }
);

Step 3: Add a "read-file" tool with security checks

Let agents pull specific files, but stop them from reading secrets:

import { readFile } from "fs/promises";
import path from "path";

server.tool(
  "read_code_file",
  "Read a file from the /src directory",
  { filename: z.string() },
  async ({ filename }) => {
    const safePath = path.join(process.cwd(), "src", filename);
    if (!safePath.startsWith(path.join(process.cwd(), "src"))) {
      return { content: [{ type: "text", text: "Access denied: path traversal blocked." }] };
    }
    try {
      const content = await readFile(safePath, "utf-8");
      return { content: [{ type: "text", text: content.slice(0, 5000) }] };
    } catch (e) {
      return { content: [{ type: "text", text: "File not found." }] };
    }
  }
);
Security note: Always validate file paths. MCP agents often run with your full shell permissions – a careless tool can leak .env files.

Step 4: Connect to the agent

Finally, start the server over stdio:

const transport = new StdioServerTransport();
await server.connect(transport);
console.error("MCP server running");

Compile and add to your agent's config (Claude Desktop example):

{
  "mcpServers": {
    "codebase-helper": {
      "command": "node",
      "args": ["/path/to/dist/index.js"]
    }
  }
}
Pro tip: Add a tool that runs curl against your internal docs or a search tool against your wiki. Any read-only API you use daily is a good MCP tool.
That's it! Restart your agent, and you can ask: "What's the next issue and which file is most relevant?" The agent will call your tools automatically.

Next steps

  • Add a tool that lists TODO comments across your codebase.
  • Create an in-memory cache so repeated reads don't hit disk.
  • Expose a vector-search index for semantic code retrieval.