跪拜 Guibai
← Back to the summary

MCP Server Development, Demystified with a macOS Maps Search Tool

How to Learn MCP Development with a Small Project

I demonstrate how to develop an MCP server with a small feature.

Image

In an AI tool, say "Search West Lake scenic area in the map" and this service will open the macOS built-in "Maps" and initiate the search.

That's the only feature. Let's see how it works.

Image

The relationship between the model and MCP

The model is responsible for understanding your words and deciding which tool to call. Tools are registered in the MCP server. The model selects them based only on name, description, and parameters. MCP is the protocol between them: the AI tool starts the server, sends the selection; the server executes and returns the result to the model.

Image

How MCP works

An MCP server does a few things internally. It communicates with the AI tool via standard input and standard output, called stdio. Only protocol messages go to stdout; logs go to stderr. The server first registers tools with name, description, and parameters. When a call arrives, it executes according to the parameters and sends the result back.

Image

This repository is called local-maps-mcp. Three files are key.

Process analysis

  1. Normally the AI tool starts src/index.js in the MCP server.
  2. When a call arrives, index.js doesn't do the map work; it just passes query to openMapSearch() in maps.js.
  3. maps.js builds an Apple Maps link with the search term in the q parameter, e.g., https://maps.apple.com/?q=西湖景区. Then it uses the system command open to open Maps. No API key for a map platform is required.
/usr/bin/open -b com.apple.Maps <map link>

-b com.apple.Maps specifies that the system "Maps" opens this link. When open returns, the request has been handed to the system.

Image

How to configure the MCP server

The AI tool needs a configuration that specifies the server name, Node.js to start it, and the entry src/index.js.

Since I use Cursor, I'll use Cursor as an example.

Cursor merges project-level and user-level configurations, with project-level taking precedence if same names.

Project-level goes in .cursor/mcp.json and is effective when opening this project.

User-level goes in ~/.cursor/mcp.json and applies to all projects on this machine. When writing to user-level, keep other existing servers in the file.

{
  "mcpServers": {
    "local-maps-mcp": {
      "command": "node",
      "args": ["${workspaceFolder}/src/index.js"]
    }
  }
}

Image

In the Agent conversation, type:

Search West Lake scenic area in the map

The model will call search_map with parameter { "query": "西湖景区" }. The system Maps comes to the foreground and receives the search. The conversation shows:

Sent search request to system Maps: 西湖景区

Image

How to publish the MCP server

Image

If you want others to use it, publish it to npm. Log in and publish both specify the official registry. During login, npm may ask for a dynamic verification code, and possibly again during publish.

Image

# In command line, go to project directory
npm login --registry https://registry.npmjs.org
npm publish --registry https://registry.npmjs.org

Seeing + [email protected] means success.

Others install the published package; the entry is no longer the source file in the repo. Configuration can be:

{
  "mcpServers": {
    "local-maps-mcp": {
      "command": "npx",
      "args": ["-y", "local-maps-mcp"]
    }
  }
}

Or install globally and set the start command to local-maps-mcp:

npm install -g local-maps-mcp --registry https://registry.npmjs.org
command -v local-maps-mcp

command -v prints the executable path, indicating the current terminal can find it.

Below is the complete code and the repository link:

Repository: https://github.com/liyufengrex/mcp_search_map