# MCP: The Protocol Connecting AI to Everything

**Author:** kelexine  
**Date:** 2025-12-07  
**Category:** AI  
**Tags:** MCP, AI, Protocol, Integration, Tools  
**URL:** https://kelexine.is-a.dev/blog/mcp-protocol-deep-dive

---

# What is MCP?

Model Context Protocol (MCP) is an open standard that allows AI models to interact with external systems. Instead of being isolated text generators, LLMs can now read files, query databases, call APIs, and execute code.

Think of MCP as a USB for AI: a universal interface that lets models plug into any tool.

## The Architecture

```
┌─────────────┐     MCP      ┌─────────────┐
│   AI Host   │◄────────────►│  MCP Server │
│ (Claude,    │              │  (Tools,    │
│  Gemini)    │              │   Data)     │
└─────────────┘              └─────────────┘
      │                            │
      │                            │
      ▼                            ▼
 User Interface            Files, APIs, DBs
```

### Core Concepts

**Tools**: Functions the AI can call
**Resources**: Data the AI can access
**Prompts**: Reusable prompt templates

## Building an MCP Server

Let's build a simple MCP server in TypeScript:

```typescript
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";

const server = new Server(
  { name: "my-mcp-server", version: "1.0.0" },
  { capabilities: { tools: {} } }
);

// Define a tool
server.setRequestHandler("tools/list", async () => ({
  tools: [{
    name: "get_weather",
    description: "Get current weather for a location",
    inputSchema: {
      type: "object",
      properties: {
        location: { type: "string", description: "City name" }
      },
      required: ["location"]
    }
  }]
}));

// Handle tool calls
server.setRequestHandler("tools/call", async (request) => {
  if (request.params.name === "get_weather") {
    const location = request.params.arguments.location;
    // Call real weather API here
    return {
      content: [{
        type: "text",
        text: `Weather in ${location}: 22°C, sunny`
      }]
    };
  }
});

// Start server
const transport = new StdioServerTransport();
await server.connect(transport);
```

## Resources: Exposing Data

```typescript
server.setRequestHandler("resources/list", async () => ({
  resources: [{
    uri: "file:///config.json",
    name: "Configuration",
    mimeType: "application/json"
  }]
}));

server.setRequestHandler("resources/read", async (request) => {
  if (request.params.uri === "file:///config.json") {
    return {
      contents: [{
        uri: request.params.uri,
        mimeType: "application/json",
        text: JSON.stringify({ api_key: "***", debug: true })
      }]
    };
  }
});
```

## Real-World MCP Servers

### Database Access
```typescript
// Query a PostgreSQL database
const dbTool = {
  name: "query_database",
  description: "Run a read-only SQL query",
  inputSchema: {
    type: "object",
    properties: {
      query: { type: "string" }
    }
  }
};

// Handler
const result = await pool.query(request.params.arguments.query);
return { content: [{ type: "text", text: JSON.stringify(result.rows) }] };
```

### File System Access
```typescript
const fsTool = {
  name: "read_file",
  description: "Read contents of a file",
  inputSchema: {
    type: "object",
    properties: {
      path: { type: "string" }
    }
  }
};

// Handler
const content = await fs.readFile(path, "utf-8");
return { content: [{ type: "text", text: content }] };
```

### API Integration
```typescript
const apiTool = {
  name: "github_issues",
  description: "List GitHub issues for a repo",
  inputSchema: {
    type: "object",
    properties: {
      repo: { type: "string", description: "owner/repo format" }
    }
  }
};

// Handler
const response = await fetch(`https://api.github.com/repos/${repo}/issues`);
const issues = await response.json();
return { content: [{ type: "text", text: JSON.stringify(issues) }] };
```

## Security Considerations

MCP servers have real system access. Treat them seriously:

1. **Input Validation**: Sanitize all inputs
2. **Least Privilege**: Only expose what's needed
3. **Rate Limiting**: Prevent abuse
4. **Logging**: Audit all tool calls
5. **Sandboxing**: Run in isolated environments

```typescript
// Example: Path traversal prevention
function validatePath(userPath: string): string {
  const resolved = path.resolve(ALLOWED_DIR, userPath);
  if (!resolved.startsWith(ALLOWED_DIR)) {
    throw new Error("Access denied");
  }
  return resolved;
}
```

## Connecting to Claude Desktop

Configure in `claude_desktop_config.json`:

```json
{
  "mcpServers": {
    "my-server": {
      "command": "node",
      "args": ["/path/to/my-mcp-server/build/index.js"]
    }
  }
}
```

## The Future of MCP

MCP is still early but growing fast:
- Official servers for popular services
- IDE integrations
- Multi-agent orchestration
- Standardized security models

## Conclusion

MCP transforms AI from a text-in-text-out box into an active participant in your workflow. It's the missing piece that makes AI actually useful for developers.

Build your own MCP servers. Connect your tools. The possibilities are endless.

---

**Resources**:
- [MCP Specification](https://spec.modelcontextprotocol.io/)
- [MCP SDKs](https://github.com/modelcontextprotocol)
- [Example Servers](https://github.com/modelcontextprotocol/servers)

---

*This content is available at [kelexine.is-a.dev/blog/mcp-protocol-deep-dive](https://kelexine.is-a.dev/blog/mcp-protocol-deep-dive)*
