How to Build a Model Context Protocol (MCP) Server
Exposing databases, local filesystems, or custom APIs to AI agents usually requires custom integration code and manual schema validation. This guide explains how to build a Model Context Protocol (MCP) server using Python and TypeScript, configure the client JSON configuration file, and connect these tools to a shared team workspace.
What Is the Model Context Protocol?
Exposing a local database, internal file tree, or custom API to an AI agent usually requires writing custom integration glue, defining bespoke schema validation, and maintaining separate endpoints. The Model Context Protocol (MCP) replaces this fragmented approach by establishing a standard, secure interface that exposes databases, local filesystems, APIs, or custom tools to LLM-powered applications using a unified JSON-RPC protocol.
Designed as an open standard by Anthropic, this protocol addresses the integration challenge for AI agents. Instead of building unique connectors for every tool, developers write a server once. Any client application that supports the protocol can instantly query the server for available tools, read resources, and run actions. You can find detailed specifications in the official Model Context Protocol documentation.
At its core, a server implements three primary primitives:
- Tools: Executable functions that the model can run with human permission.
- Resources: Read-only data sources such as file content, database rows, or API responses.
- Prompts: Reusable prompt templates that guide the model through specific workflows.
For local development, client applications communicate with the server over standard input and output (stdio) transport. For remote or containerized setups, the protocol supports HTTP-based Server-Sent Events (SSE). By standardizing these communication channels, developers can focus on writing clean business logic rather than debugging transport protocols.
How to Build an MCP Server in Python
The Python ecosystem offers FastMCP, a high-level framework designed to minimize boilerplate. FastMCP uses Python decorators to automatically generate schemas and validate input parameters, allowing you to expose functions in just a few lines of code.
To begin, create a clean virtual environment and install the required packages. Using the modern package manager uv simplifies this installation process. Run the following command in your terminal:
pip install fastmcp
Create a file named server.py and write the server initialization, tool registration, and resource declaration:
from fastmcp import FastMCP
mcp = FastMCP("Local Helper")
@mcp.tool
def calculate_file_hash(path: str) -> str:
"""Calculate the SHA-256 hash of a local file to verify integrity."""
import hashlib
import os
if not os.path.exists(path):
return f"Error: File at {path} does not exist."
sha256 = hashlib.sha256()
try:
with open(path, "rb") as f:
for chunk in iter(lambda: f.read(4096), b""):
sha256.update(chunk)
return sha256.hexdigest()
except Exception as e:
return f"Error reading file: {str(e)}"
@mcp.resource("config://app")
def get_app_config() -> str:
"""Get the application configuration template."""
return """db_host=localhost
db_port=5432
debug=true"""
if __name__ == "__main__":
mcp.run()
When writing a python server that communicates over standard input and output (stdio), you must log debugging messages to standard error (stderr). Writing print statements or other logs directly to standard output (stdout) will corrupt the JSON-RPC message stream and break the client connection. Use the standard Python logging module configured to target sys.stderr or use FastMCP's built-in logging utilities to monitor server behavior.
How to Build an MCP Server in TypeScript
For Node.js environments, the official TypeScript SDK provides a type-safe approach to defining servers. The modern SDK features the McpServer class, which offers a clean registration API and uses Zod for schema validation.
First, initialize a new Node.js project and install the necessary dependencies:
npm init -y
npm install @modelcontextprotocol/sdk zod
npm install --save-dev typescript @types/node tsx
Configure a basic tsconfig.json to handle ES Modules:
{
"compilerOptions": {
"target": "ES2022",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"esModuleInterop": true,
"strict": true,
"outDir": "./dist"
}
}
Create a file named index.ts and write the server setup:
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: "developer-utility-server",
version: "1.0.0"
});
server.registerTool(
"generateUuid",
{
description: "Generate a cryptographically secure random UUID.",
inputSchema: z.object({
prefix: z.string().optional()
})
},
async ({ prefix }) => {
const crypto = await import("node:crypto");
const uuid = crypto.randomUUID();
const result = prefix ? `${prefix}-${uuid}` : uuid;
return {
content: [{ type: "text", text: result }]
};
}
);
server.registerResource(
"system-info",
"resource://system/info",
{
name: "System Information",
description: "Static system information for the agent"
},
async (uri) => ({
contents: [{
uri: uri.href,
mimeType: "text/plain",
text: `Operating System: macOS
Node.js Version: 20.0.0`
}]
})
);
async function run() {
const transport = new StdioServerTransport();
await server.connect(transport);
}
run().catch((error) => {
console.error("Fatal error running server:", error);
process.exit(1);
});
As with the Python implementation, remember that Node.js logs must go to standard error. Using console.log will write to stdout, corrupting the communication transport. Always use console.error for developer logging and debugging.
How to Configure the Client JSON File
Once you build your server, you need to connect it to an MCP client like Claude Desktop. Clients use a JSON configuration file to discover, launch, and authenticate local servers.
On macOS, the configuration file is located at:
~/Library/Application Support/Claude/claude_desktop_config.json
On Windows, the configuration file is located at:
%APPDATA%\Claude\claude_desktop_config.json
Open this file in a text editor. If the file does not exist, create it. Add your server configuration under the mcpServers key. Here is a configuration example containing both the Python and TypeScript servers:
{
"mcpServers": {
"python-helper": {
"command": "uv",
"args": [
"run",
"--path",
"/absolute/path/to/server.py"
]
},
"typescript-utility": {
"command": "npx",
"args": [
"tsx",
"/absolute/path/to/index.ts"
],
"env": {
"MY_API_KEY": "your-key-here"
}
}
}
}
Make sure to replace /absolute/path/to/ with the actual absolute path to your script files. If your server requires environment variables, define them inside the env object as shown in the TypeScript configuration. Once the configuration is saved, restart Claude Desktop. The application will launch your servers in the background using standard input and output streams. You can read more in the MCP server development guide. You will see a plug icon in the chat box, indicating that the tools are registered and ready for the model to use.
Troubleshooting connection failures requires inspecting the client logs. Claude Desktop writes logs to:
~/Library/Logs/Claude/mcp.log on macOS
%APPDATA%\Claude\Logs\mcp.log on Windows
Open these log files to check for syntax errors, wrong command paths, or standard output corruption messages.
Build and connect your custom MCP servers
Store your configurations, connect custom MCP servers to a shared workspace with a consolidated MCP toolset, and track per-file version history. Start your 14-day free trial today.
How to Scale Local MCP Servers to Collaborative Workspaces
Running local servers over stdio transport works well for single developers, but it does not scale to team environments. When several agents and humans need to coordinate, sharing local scripts is inefficient. The solution is not to run fragmented local setups, but to use a shared, intelligent workspace that serves as a common coordination substrate.
Instead of raw object storage, team workspaces like Fast.io provide a shared workspace where agents and humans collaborate on the same files and shares. Rather than maintaining custom transport code, Fast.io exposes action-based tools via its own consolidated MCP toolset. This server supports Streamable HTTP endpoints at /mcp and legacy Server-Sent Events (SSE) at /sse, allowing developers to connect any remote model to their shared files. You can read about this setup in the Fast.io developer documentation and access the Fast.io MCP guide or Fast.io agent onboarding specifications.
Fast.io complements your custom tools with built-in productivity features:
- Per-File Version History: When two or more agents write to the same folder, they can overwrite changes without realizing it. Fast.io tracks version history automatically, allowing teams to restore prior versions and audit updates.
- Metadata Views: Turn files into a queryable database by describing fields in natural language. AI automatically designs schemas with columns for Text, Integer, Decimal, Boolean, URL, JSON, and Date & Time, and processes PDFs, Word documents, or scanned pages without templates.
- Intelligence Mode: Uploaded documents are automatically indexed. Agents can query files using semantic search and get answers backed by page-level citations.
- Ownership Transfer: Agents can create workspaces, set up folder structures, populate them with files, and then transfer the organization to a human teammate using a secure claim link.
Setting up this workspace takes minutes. If you want to connect your agents to a shared context, you can create a paid organization on the pricing page or register via the storage for agents portal. Every new organization begins with a 14-day free trial that requires a credit card. Paid plans include Starter at $29 per month, Business at $99 per month, and Growth at $299 per month, providing flexible options for teams of all sizes.
Frequently Asked Questions
How do I connect an MCP server?
You connect an MCP server by adding its path and startup commands to your client's JSON configuration file. For local clients like Claude Desktop, specify the runtime command (such as uv or node) and absolute paths to the script under the mcpServers key. For remote environments, connect to HTTP endpoints running Server-Sent Events (SSE).
What language can you use to build an MCP server?
You can build an MCP server in any programming language that supports standard I/O streams or HTTP transports. The official SDKs support TypeScript (Node.js, Bun, and Deno) and Python (using high-level frameworks like FastMCP). Other community-maintained SDKs support Go, Rust, Java, Kotlin, C#, and Ruby.
What is the Model Context Protocol?
The Model Context Protocol (MCP) is an open standard designed by Anthropic to solve the tool-integration problem for AI agents. It establishes a standard, secure interface that exposes databases, local filesystems, APIs, or custom tools to LLM-powered applications using a unified JSON-RPC protocol.
Related Resources
Build and connect your custom MCP servers
Store your configurations, connect custom MCP servers to a shared workspace with a consolidated MCP toolset, and track per-file version history. Start your 14-day free trial today.