Building a Local MCP Service from Scratch: A Complete Guide to STDIO Mode Implementation and LLM Integration

96 Views
No Comments

We’ve already covered MCP in previous content. If you’re interested, you can check out our earlier article:

As LLM (Large Language Model) application scenarios deepen, official entities and enterprises have successively launched customized MCP (Model Context Protocol) services. GitLab uses MCP for tool calls in code collaboration scenarios, Alipay leverages it for function expansion in payment scenarios, and Amap integrates it for location-based service interactions—all achieving seamless connectivity between LLMs and vertical tools via the MCP protocol. For users with development capabilities, there’s no need to rely on third-party services; you can build an MCP service tailored to your business needs independently. This article will start with the working principles of MCP, take the STDIO transmission mode as an example, and provide a comprehensive walkthrough of building a local MCP service, testing it, and integrating it with an LLM (using Cursor as an example), helping developers quickly master the practical application of the MCP protocol.

1. Core Working Principles of MCP Services: An Overview of Transmission Methods

The core value of the MCP protocol lies in establishing a communication bridge between LLMs and external tools. Its transmission method directly determines the service’s applicable scenarios and data interaction efficiency. Currently, mainstream MCP transmission methods are divided into two types: STDIO and SSE. These two methods differ significantly in communication mode and use cases, so developers should choose the appropriate one based on business requirements.

1.1 STDIO Transmission Mode

STDIO (Standard Input/Output) refers to standard input and output streams, which enable data exchange through command-line input (stdin) and output (stdout).

  • Communication Features: Relies on inter-process communication (IPC) locally, with no network dependencies and low data transmission latency. It is suitable for lightweight integration between local tools and LLMs.
  • Use Cases: Local script tools (e.g., calculation tools, file processing tools) and scenarios that do not require cross-device calls—such as the local addition tool we will implement in this article.

1.2 SSE Transmission Mode

SSE (Server-Sent Events) enables one-way communication based on the HTTP protocol, supporting only the server to actively push data to the client.

  • Communication Features: Depends on the network environment, allowing cross-device and cross-terminal tool calls, and supports real-time data push (e.g., log updates, real-time calculation results).
  • Use Cases: Cloud-based tool services (e.g., online data analysis tools, remote API calls) and scenarios requiring continuous data push—such as integrating real-time monitoring systems with LLMs.

2. Building an MCP Service in STDIO Mode: From Environment Setup to Code Implementation

In this section, we will build an STDIO-mode MCP service based on the Node.js environment to address the requirement of “LLM-triggered addition operations.” The core dependencies include the official MCP SDK (@modelcontextprotocol/sdk) for service initialization and tool definition, and the zod library for parameter validation to ensure the legitimacy of input data.

2.1 Preparatory Environment Setup

Before building the MCP service, you need to configure the basic development environment to ensure that dependent tools run properly:

  1. Install Node.js and npm: It is recommended to use Node.js version 16.x or higher. Verify the installation results using the node -v and npm -v commands.
  2. Install the pnpm package manager: Compared to npm, pnpm offers faster dependency installation and lower disk usage. Execute npm install -g pnpm to complete the global installation.
  3. Understand core dependency libraries:
    • @modelcontextprotocol/sdk: The official MCP development kit, providing core capabilities such as service initialization, tool registration, and transmission protocol encapsulation.
    • zod: A TypeScript-first data validation library used to define the format of tool input parameters (e.g., numeric type validation) and prevent service errors caused by invalid parameters.

2.2 Project Initialization and Dependency Installation

Follow these steps to create a project directory and install core dependencies:

  1. Create a project folder: Execute mkdir add-mcp && cd add-mcp to create a project directory named “add-mcp” and navigate into it.
  2. Initialize project configuration: Execute pnpm init to generate a package.json file for managing project dependencies and configurations.
  3. Install core dependencies: Execute pnpm add @modelcontextprotocol/sdk zod to add the MCP SDK and parameter validation library to the project dependencies.
  4. Configure ES Module syntax: Add "type": "module" to package.json to ensure the project supports the import/export modular syntax and avoids errors caused by mixing CommonJS and ES Modules.

2.3 Writing Core MCP Service Code (index.mjs)

Create an index.mjs file and use the MCP SDK to implement service initialization, addition tool registration, and STDIO transmission configuration. The code is parsed section by section below:

// Import core MCP service modules and STDIO transmission modules
import {McpServer, ResourceTemplate} from "@modelcontextprotocol/sdk/server/mcp.js";
import {StdioServerTransport} from "@modelcontextprotocol/sdk/server/stdio.js";
// Import zod for parameter validation
import {z} from "zod";

// 1. Initialize the MCP service: Define the service name and version for easy identification and management later
const server = new McpServer({
  name: "Addition-MCP-Service", // Service name, which must correspond to client configurations
  version: "1.0.0" // Service version, used for iteration management
});

// 2. Register the addition tool: Define the tool name, description, parameter format, and execution logic
server.tool(
  "add", // Unique tool identifier; the LLM will call the tool using this name
  "Calculate the sum of two numbers (a and b)", // Tool description to help the LLM understand the tool's function
  {a: z.number(), b: z.number()}, // Parameter validation rules: a and b must be numeric types
  async ({a, b}) => { // Tool execution logic: Receive parameters and return calculation results
    return {content: [{ type: "text", text: `The sum of ${a} and ${b} is: ${a + b}` }] // Result format, supporting text, JSON, etc.
    };
  }
);

// 3. Start the service: Configure STDIO transmission and monitor data interactions
async function main() {const transport = new StdioServerTransport(); // Initialize an STDIO transmission instance
  await server.connect(transport); // Establish a connection between the service and STDIO transmission
  console.log("STDIO-MCP Service started successfully. Waiting for tool calls...");
}

// Execute the startup function
main().catch(err => {console.error("MCP Service startup failed:", err.message);
});

Explanation of core code logic:

  • Service Initialization: The McpServer class is used to define service metadata, ensuring the client can accurately identify the service.
  • Tool Registration: The server.tool() method is the core. The zod validation rules prevent non-numeric parameters from being passed in (avoiding calculation errors), and the returned results follow a standardized format for easy parsing by the LLM.
  • STDIO Transmission: The StdioServerTransport class encapsulates the processing of standard input and output streams. There’s no need to manually manage stream reading and writing, reducing development complexity.

3. MCP Service Testing: Verifying Functionality with the Inspector Tool

After building the service, you need to use the official testing tool @modelcontextprotocol/inspector to verify whether the tool responds normally. This avoids troubleshooting difficulties caused by service abnormalities when integrating directly with the LLM. The testing process consists of three steps: “launch the testing tool,” “connect to the service,” and “call the tool.”

3.1 Launch the Inspector Testing Tool

No additional dependencies need to be installed; directly execute the official testing tool via npx:

npx @modelcontextprotocol/inspector node index.mjs

After executing the command, the tool will automatically start a local service and prompt you to access the address: http://127.0.0.1:6274/.

3.2 Connect to the MCP Service and Test the Tool

Open a browser and visit http://127.0.0.1:6274/, then follow these steps to complete the test:

Building a Local MCP Service from Scratch: A Complete Guide to STDIO Mode Implementation and LLM Integration
  1. Connect to the service: Click the “Connect” button in the upper left corner of the page. If the connection is successful, the button status will change to “Connected,” and the console will output a “Client connected” log.
  2. List tools: Click the “List Tools” button. The page will display a list of registered tools (in this article, it is the “add” tool), verifying that the tool was registered successfully.
  3. Call the addition tool:
    • Click the “add” tool in the tool list to bring up the parameter input box.
    • Enter test parameters (e.g., a=10b=20) and click the “Run Tool” button.
    • Check the returned result: The page will display “The sum of 10 and 20 is: 30“, indicating the tool executed normally. If you enter non-numeric parameters (e.g., a="abc"), a zod validation error will be triggered, verifying that the parameter validation function works.
Building a Local MCP Service from Scratch: A Complete Guide to STDIO Mode Implementation and LLM Integration

4. LLM Integration: Configuring the MCP Service with Cursor as an Example

After passing the test, you can integrate the local MCP service into the LLM to implement a complete workflow: “LLM automatically identifies requirements → calls the MCP tool → returns results.” This section uses Cursor (a commonly used LLM for coding scenarios) as an example to explain client configuration steps and functionality verification.

Building a Local MCP Service from Scratch: A Complete Guide to STDIO Mode Implementation and LLM Integration

4.1 MCP Configuration in the Cursor Client

Cursor associates local MCP services through configuration files. Follow these steps to modify the configuration:

  1. Open the Cursor configuration file: Go to Cursor Settings, find the “MCP Servers” configuration item, and click “Edit Config” to enter the JSON configuration interface.
  2. Add MCP service configuration: Add a new “add-mcp” service configuration to the mcpServers object, as shown in the example below:
{
  "mcpServers": {
    "add-mcp": { // Service name, custom and unique
      "type": "stdio", // Transmission method, consistent with the server (STDIO)
      "command": "npx", // Startup command used to execute the MCP service
      "args": [
        "-y", // pnpm/npx parameter to automatically confirm dependency installation
        "node", // Command to execute the Node.js script
        "D:\\kelen\\study\\add-mcp\\index.mjs" // Path to the local MCP service code (replace with the actual path)
      ]
    }
  }
}
  1. Verify configuration validity: After saving the configuration, Cursor will automatically attempt to connect to the MCP service. If the configuration is correct, a “green indicator” will appear next to the service name, indicating a successful connection. If it shows red, check whether the path is correct and whether the service can start normally.
Building a Local MCP Service from Scratch: A Complete Guide to STDIO Mode Implementation and LLM Integration

4.2 Verify LLM Tool Calling Functionality

After configuration, enter an addition-related question in the Cursor chat interface to test whether the LLM can automatically call the MCP tool:

  • Enter the question: “Calculate the sum of 156 and 248.”
  • Observe the response: Cursor will recognize the “addition operation” requirement, automatically call the “add-mcp” service, and return the result “The sum of 156 and 248 is: 404.” There’s no need to perform manual calculations, enabling seamless integration between the tool and the LLM.

5. Conclusion and Expansion: The Value of MCP Services and Advanced Directions

This article completed the implementation of an STDIO-mode MCP service through a workflow of “principle analysis → building and implementation → testing → integration.” Its core value lies in verifying the flexibility of the MCP protocol—developers can customize tools based on business needs, break free from reliance on third-party services, and simultaneously enable the LLM to achieve the intelligent capability of “independently deciding to call tools,” significantly improving work efficiency (e.g., in scenarios such as automatic calculation, data processing, and API calls).

Advanced Expansion Directions

  1. Tool Function Expansion: Based on the existing service, add more calculation tools (e.g., multiplication, division) or integrate external APIs (e.g., weather queries, stock data interfaces). Register additional tools via server.tool() to meet complex requirements.
  2. Transmission Mode Switching: If cross-device calls are required, switch from STDIO mode to SSE mode. Replace StdioServerTransport with SseServerTransport and configure an HTTP port to support remote client connections.
  3. Error Handling Optimization: Add exception handling to the tool execution logic (e.g., division by zero, API call failures) and extend parameter validation rules via zod (e.g., numerical range restrictions) to improve service stability.
  4. Multi-Model Integration: In addition to Cursor, the MCP service can be integrated into other LLMs such as ChatGPT and ERNIE Bot. Most LLMs that support the MCP protocol provide similar configuration entrances, and the process is consistent with that of Cursor.
END
 0
Fr2ed0m
Copyright Notice: Our original article was published by Fr2ed0m on 2025-10-21, total 11412 words.
Reproduction Note: Unless otherwise specified, all articles are published by cc-4.0 protocol. Please indicate the source of reprint.
Comment(No Comments)