跪拜 Guibai
← All articles
JavaScript

A Single Natural-Language Command Drives Map Search, File I/O, and Browser Automation via Three MCP Servers

By mONESY ·
Read original on juejin.cn ↗ Google Translate ↗ Alt translation

Mixing cloud and local MCP servers in one agent run is still under-documented. This walkthrough gives a concrete, copy-pasteable pattern for combining hosted APIs with local browser and filesystem tools, plus the exact error fixes that trip up first-timers — especially return-format mismatches and Chrome debug-port setup.

Summary

The setup uses DeepSeek-V4-Pro as the reasoning model and LangChain’s MultiServerMCPClient to bridge two transport modes: SSE for Amap’s hosted map service and stdio for local filesystem and Chrome debugging tools. A single natural-language query triggers a multi-turn loop where the model decides which tool to call, feeds results back into context, and stops when no further tool calls are needed. The full run — POI search, image retrieval, tab creation, and page-title rewriting — completes without hand-coded orchestration.

All code is provided as a single runnable TypeScript file. The author includes fixes for five common failure modes: misconfiguring the cloud MCP as a local process, using the wrong client variable name, mismatched tool-return formats, missing Chrome debug-port startup, and top-level await errors in Node.js. A finally block guarantees MCP connections close even on exceptions, addressing a frequent resource-leak pain point in agent scripts.

Takeaways
DeepSeek-V4-Pro with temperature 0 provides deterministic tool selection across multi-turn agent loops.
LangChain’s MultiServerMCPClient handles SSE (Amap cloud) and stdio (filesystem, Chrome) transports in a single config object.
The agent loop binds all discovered MCP tools to the model, invokes them based on tool_calls, and feeds ToolMessage results back for the next iteration.
A three-branch type check (string, object with .text, or JSON.stringify fallback) normalizes inconsistent MCP return shapes.
Chrome DevTools MCP requires launching Chrome with --remote-debugging-port=9222 before the agent runs.
Encapsulating the run in an async main() function avoids Node.js top-level await errors and ensures mcpClient.close() executes in a finally block.
Conclusions

Most MCP tutorials show a single server; the real integration challenge — and where bugs surface — is mixing cloud SSE and local stdio servers in one agent. This code surfaces exactly those pain points.

The return-format normalization block is small but critical. Without it, different MCP servers’ JSON shapes cause silent undefined errors that are hard to trace in a multi-turn loop.

Using a finally block for resource cleanup is standard practice, yet many agent demos omit it. The explicit close() call here prevents port exhaustion and zombie Chrome processes that accumulate during development.

Concepts & terms
MCP (Model Context Protocol)
An open protocol that standardizes how AI models discover and call external tools. Servers expose capabilities (APIs, file systems, browsers) via stdio or SSE transports, and clients like LangChain’s adapter present them as callable tools to the model.
SSE (Server-Sent Events) transport in MCP
A long-lived HTTP connection where the server pushes events to the client. In MCP, it allows cloud-hosted tools like Amap’s map service to be used without running a local process, requiring only a URL and API key.
stdio transport in MCP
A local inter-process communication mode where the MCP client launches a server as a child process (e.g., via npx) and communicates over standard input/output. Used for tools that need direct access to the local machine, such as filesystem operations or Chrome debugging.
Tool binding in LangChain
The model.bindTools(tools) call attaches a list of tool definitions to a chat model so that the model can decide when and how to invoke them. The model returns tool_calls in its response, which the agent loop then executes.
Source: juejin.cn ↗ Google Translate ↗ Backup ↗