What is MCP (Model Context Protocol)?
MCP is an open standard by Anthropic for connecting LLMs to external tools and data sources through a common interface. It lets AI assistants read files, query databases, and call APIs without custom integration code per tool.
Overview
Key Points
- •MCP defines three primitives: tools (functions the AI can call), resources (data the AI can read), and prompts (reusable prompt templates).
- •Servers can expose local resources (files, databases) or remote APIs through a standardised JSON-RPC interface.
- •Clients include: Claude Desktop, Cursor, VS Code extensions, and any custom app built with the MCP SDK.
- •Pre-built MCP servers exist for: filesystem, GitHub, PostgreSQL, Slack, Google Drive, Jira, and dozens more.
- •MCP runs over stdio (local servers) or HTTP+SSE (remote servers) making it easy to self-host.
- •MCP does not handle authentication or authorisation - that is left to each server implementation.
Examples
Using MCP in Claude Desktop (claude_desktop_config.json)
json{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/Users/alice/projects"]
},
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "ghp_your_token_here"
}
},
"postgres": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-postgres", "postgresql://localhost/mydb"]
}
}
}After adding this config and restarting Claude Desktop, Claude can read your local files, browse GitHub repos, and query your PostgreSQL database directly.
Building a minimal MCP server in TypeScript
typescriptimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import { z } from 'zod';
const server = new McpServer({
name: 'weather-server',
version: '1.0.0',
});
// Register a tool the LLM can call
server.tool(
'get_current_weather',
'Get the current weather for a city',
{ city: z.string().describe('City name, e.g. "London"') },
async ({ city }) => {
const data = await fetchWeatherApi(city);
return {
content: [{
type: 'text',
text: `${city}: ${data.temp}°C, ${data.description}`,
}],
};
}
);
// Register a resource (static or dynamic data the LLM can read)
server.resource(
'weather://forecast/today',
'Today's global weather summary',
async (uri) => ({
contents: [{
uri: uri.href,
text: await getDailyForecastSummary(),
}],
})
);
// Start the server over stdio
const transport = new StdioServerTransport();
await server.connect(transport);Querying an MCP server programmatically (MCP client)
typescriptimport { Client } from '@modelcontextprotocol/sdk/client/index.js';
import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
const transport = new StdioClientTransport({
command: 'node',
args: ['./weather-server.js'],
});
const client = new Client({ name: 'my-app', version: '1.0.0' });
await client.connect(transport);
// List available tools
const { tools } = await client.listTools();
console.log(tools.map(t => t.name)); // ['get_current_weather']
// Call a tool
const result = await client.callTool({
name: 'get_current_weather',
arguments: { city: 'Berlin' },
});
console.log(result.content[0].text); // 'Berlin: 18°C, partly cloudy'Pro Tip
Start with the pre-built MCP servers from the official repository (github.com/modelcontextprotocol/servers) before building your own. The filesystem, GitHub, and PostgreSQL servers cover the majority of use cases out of the box. Build a custom server only when you need access to a proprietary internal API.