What Is an MCP Server?
Model Context Protocol (MCP) is Anthropic's open standard for giving AI models access to tools, data, and services. An MCP server exposes capabilities that any MCP-compatible client (Claude Desktop, Cursor, your custom app) can use.
Building one is straightforward. Here's the complete pattern.
Project Setup
mkdir my-mcp-server && cd my-mcp-server
npm init -y
npm install @modelcontextprotocol/sdk zod
npm install -D typescript @types/node tsx
// tsconfig.json
{
"compilerOptions": {
"target": "ES2022",
"module": "Node16",
"moduleResolution": "Node16",
"outDir": "./dist",
"strict": true
}
}
Basic MCP Server
// src/index.ts
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 { z } from 'zod'
const server = new Server(
{ name: 'my-mcp-server', version: '1.0.0' },
{ capabilities: { tools: {} } }
)
// List available tools
server.setRequestHandler(ListToolsRequestSchema, async () => ({
tools: [
{
name: 'get_time',
description: 'Get the current time in a timezone',
inputSchema: {
type: 'object',
properties: {
timezone: {
type: 'string',
description: 'IANA timezone (e.g. America/New_York)',
}
},
required: ['timezone']
}
},
{
name: 'calculate',
description: 'Evaluate a mathematical expression',
inputSchema: {
type: 'object',
properties: {
expression: { type: 'string', description: 'Math expression to evaluate' }
},
required: ['expression']
}
}
]
}))
// Handle tool calls
server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params
if (name === 'get_time') {
const { timezone } = args as { timezone: string }
try {
const time = new Date().toLocaleString('en-US', { timeZone: timezone })
return { content: [{ type: 'text', text: `Current time in ${timezone}: ${time}` }] }
} catch {
return { content: [{ type: 'text', text: `Invalid timezone: ${timezone}` }], isError: true }
}
}
if (name === 'calculate') {
const { expression } = args as { expression: string }
// Safe eval alternative
try {
const result = Function('"use strict"; return (' + expression + ')')
return { content: [{ type: 'text', text: `${expression} = ${result()}` }] }
} catch (e) {
return { content: [{ type: 'text', text: `Error: ${e}` }], isError: true }
}
}
return { content: [{ type: 'text', text: `Unknown tool: ${name}` }], isError: true }
})
// Start server
async function main() {
const transport = new StdioServerTransport()
await server.connect(transport)
console.error('MCP server running on stdio')
}
main().catch(console.error)
Claude Desktop Configuration
// ~/Library/Application Support/Claude/claude_desktop_config.json
{
"mcpServers": {
"my-mcp-server": {
"command": "node",
"args": ["/path/to/my-mcp-server/dist/index.js"],
"env": {
"MY_API_KEY": "your-api-key-here"
}
}
}
}
Adding Resources (Read-only Data)
import { ListResourcesRequestSchema, ReadResourceRequestSchema } from '@modelcontextprotocol/sdk/types.js'
const server = new Server(
{ name: 'my-mcp-server', version: '1.0.0' },
{ capabilities: { tools: {}, resources: {} } } // Add resources capability
)
server.setRequestHandler(ListResourcesRequestSchema, async () => ({
resources: [
{
uri: 'config://app/settings',
name: 'Application Settings',
mimeType: 'application/json'
}
]
}))
server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
if (request.params.uri === 'config://app/settings') {
return {
contents: [{
uri: 'config://app/settings',
mimeType: 'application/json',
text: JSON.stringify({ theme: 'dark', language: 'en' })
}]
}
}
throw new Error('Resource not found')
})
Security: What to Check Before Installing
MCP servers run on your machine with your credentials. Before installing any server:
- Input validation -- does it validate all tool inputs with schemas?
- Command injection -- does it ever pass user input to shell commands?
- Path traversal -- does it use user-provided file paths directly?
- Hardcoded secrets -- are API keys in the source code?
- SSRF -- can it make arbitrary HTTP requests based on user input?
The MCP Security Scanner checks all 22 of these rules automatically. Scan any MCP server before you install it.
$29/mo at whoffagents.com
Top comments (0)