AI & Agents

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.

Fast.io Editorial Team 8 min read
MCP standardizes how AI models connect to local resources and APIs.

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.

Fastio features

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.

An interface showing intelligent file indexing and semantic search capabilities within a shared team workspace.

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

Fastio features

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.