DEV Community

Shada Daab
Shada Daab

Posted on

Setting Up an MCP Server

1. Choose Your Environment (Local vs. Cloud)

  • Local (developer machine): For testing or desktop apps, you can run an MCP server as a local process. Any machine with Node.js installed can host an MCP server. Many reference servers are available as npm packages – for example, the filesystem server (which exposes files as tools) is published as @modelcontextprotocol/server-filesystem.
  • Cloud (remote): For production or web-based use, host the MCP server on a cloud platform. You can use services like Cloudflare WorkersAzure FunctionsAWS Lambda, or any Node-friendly web host. Cloudflare even provides boilerplate and OAuth handling for remote MCP servers. The key is that the server must have an HTTPS endpoint that supports the MCP transport (Streamable HTTP + optional Server-Sent Events). ##

2. Install Dependencies

Make sure you have Node.js (latest LTS) installed. Then initialize a project and install the MCP SDK:

npm install @modelcontextprotocol/sdk express
Enter fullscreen mode Exit fullscreen mode

The @modelcontextprotocol/sdk package contains the TypeScript/JavaScript SDK for building MCP servers and clients.

3. Create Your MCP Server (Example)

Using the TypeScript/JS SDK, you define an McpServer, register tools, and run an HTTP or stdio transport. For example, to make a simple “addition” tool in a Node.js server (server.ts):

import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';

// Create an MCP server instance
const server = new McpServer({
    name: 'demo-server',
    version: '1.0.0'
});

// Register a simple addition tool
server.registerTool(
  'add',
  {
    title: 'Addition Tool',
    description: 'Add two numbers',
    inputSchema: { a: z.number(), b: z.number() },         // e.g. use zod for schemas
    outputSchema: { result: z.number() }
  },
  async ({ a, b }) => {
    // This function runs when the AI calls the 'add' tool
    const sum = a + b;
    return {
      // The AI receives the text and structured output
      content: [{ type: 'text', text: `Result: ${sum}` }],
      structuredContent: { result: sum }
    };
  }
);

Enter fullscreen mode Exit fullscreen mode

This example shows the core of an MCP server: you create an McpServer, then use registerTool(toolName, metadata, handler) to expose a function. In this case, an AI can call the “add” tool with {a:1, b:2} to get {result:3}. The full SDK README provides this example in context.

4. Expose the Server over a Transport

Next, tie the MCP server into an HTTP endpoint so clients can connect. A common pattern with Express is:

import express from 'express';
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';

const app = express();
app.use(express.json());

// HTTP endpoint for MCP (Streamable HTTP transport)
app.post('/mcp', async (req, res) => {
  // Create a new transport for each request
  const transport = new StreamableHTTPServerTransport({ enableJsonResponse: true });
  // Clean up on close
  res.on('close', () => transport.close());

  // Connect transport to our server and handle the incoming JSON-RPC
  await server.connect(transport);
  await transport.handleRequest(req, res, req.body);
});

// Start listening
const port = 3000;
app.listen(port, () => {
  console.log(`MCP server running at http://localhost:${port}/mcp`);
});

Enter fullscreen mode Exit fullscreen mode

This skeleton (adapted from the MCP SDK docs) spins up an HTTP POST route at /mcp. MCP clients can then send JSON requests or open an SSE stream here. The key is to call server.connect(transport) and transport.handleRequest(req, res, req.body) for each request. (The SDK docs show this complete example.)

5. Quick-start with Reference Servers (no coding)

For common tasks, you don’t even have to write code. The community maintains ready-to-run MCP server packages. For example, the Filesystem Server (providing file-read/write tools) can be launched with one command. In a terminal, run:

npx -y @modelcontextprotocol/server-filesystem /path/to/dir
Enter fullscreen mode Exit fullscreen mode

This starts an MCP server that grants access to the specified folder. You’ll then configure your AI client (or Claude Desktop, VS Code, etc.) to connect to this local server. Anthropic’s official docs show exactly this command for testing. In the same way, there are packages for other servers (e.g. server-gitserver-google-drive, etc.) listed in the MCP GitHub repo.

6. Deploying to the Cloud

When you want your MCP server accessible on the internet, deploy it like any web service. Some options:

  • Cloudflare Workers: Cloudflare provides a streamlined flow. Their blog explains how a Worker can handle MCP (with built-in OAuth support) in minutes. You can bundle your TypeScript server code into a Worker and use Cloudflare’s workers-oauth-provider library to handle authentication.
  • Azure Functions / AWS Lambda / Containers: You can host the above Express code in Azure Functions (they even have a sample project) or any Node.js server environment. The only requirement is an HTTPS endpoint for the MCP transport (HTTP+SSE). For example, an Azure Functions template shows how to expose an /mcp SSE endpoint secured with function keys (see MS sample).
  • Generic Server: Any cloud VM or container works. Just ensure the host has Node, and forward port 3000 (or your port). Configure SSL for production (HTTPS is required for SSE). Once deployed, remote clients will point to your server’s URL instead of localhost.

Integrating MCP into JavaScript Apps

Once your MCP server is running, you can write a JavaScript client to use it. The MCP TypeScript SDK provides Client classes and transports. The common transports for JS are stdio (for local subprocess servers) and SSE/HTTP (for remote servers).

1. Using the MCP Client SDK

Install the same SDK in your JS project:

npm install @modelcontextprotocol/sdk
Enter fullscreen mode Exit fullscreen mode

Then you can create a client and connect. For a local subprocess server (stdin/stdout transport), use StdioClientTransport. For example:

import { Client } from '@modelcontextprotocol/sdk/client/index.js';
import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';

const client = new Client({ name: 'my-app' });
const transport = new StdioClientTransport({
  command: 'npx',
  args: ['-y', 'my-mcp-server@latest']  // e.g. launch a server via npx
});
await client.connect(transport);
Enter fullscreen mode Exit fullscreen mode

This spawns the server (via npx) as a subprocess and communicates with it over stdio. The code snippet above is adapted from LangChain’s tutorial for MCP. After connect(), the client is linked to the server and ready to call tools.

For a remote (HTTP+SSE) server, use SSEClientTransport or the newer StreamableHTTPClientTransport. For example:

import { Client } from '@modelcontextprotocol/sdk/client/index.js';
import { SSEClientTransport } from '@modelcontextprotocol/sdk/client/sse.js';

const client = new Client({ name: 'my-app' });
const transport = new SSEClientTransport('https://myserver.com/mcp');
await client.connect(transport);

Enter fullscreen mode Exit fullscreen mode

This opens a long-lived Server-Sent Events connection to the /mcp endpoint of your server. Once connected, the client and server exchange JSON-RPC messages over this channel.

2. Calling Tools from JavaScript

With the client connected, you can invoke any registered tool on the server. The SDK provides a simple method:

const result = await client.callTool({
  name: 'add',
  arguments: { a: 5, b: 7 }
});
console.log(result.structuredContent); // { result: 12 }

Enter fullscreen mode Exit fullscreen mode

This sends a tool-invocation request to the server’s add tool, and awaits the response. The example above (from the SDK docs) shows calling a tool named “example-tool”. The result includes both textual content and structured output as defined by the server.

You can also read resources (if the server provides any) via client.readResource({...}) or listen to server notifications. In practice, many JS developers use higher-level libraries (e.g. LangChain/MCP adapters) to wrap these calls in agent patterns, but the raw callTool method is there if you need low-level control.

3. Example: Integrating in an App

Suppose you have a Node app that needs to list files via an MCP filesystem server. You might write:

// (After connecting client as above...)
const files = await client.callTool({
  name: 'list-files',
  arguments: { path: '/project', pattern: '*.js' }
});
console.log("JS files:", files.structuredContent.files);
Enter fullscreen mode Exit fullscreen mode

Behind the scenes, the MCP server’s “list-files” tool runs and returns the list of files (in both text and JSON). Your app need not know how the server implemented it. The protocol ensures a clean handoff.

Best Practices and Pitfalls

  • Least Privilege Access. Only expose the tools and data the AI truly needs. For a filesystem server, explicitly list the directories it may touch. Never mount root or sensitive paths. By default, grant as narrow permissions as possible (e.g. read-only vs. write). Remember that a server runs with the user’s privileges, so be careful – the user approving is effectively giving full access of those resources.
  • Validate Inputs/Outputs. Define clear schemas for tool arguments and return values (the MCP SDK supports JSON schemas or libraries like Zod as shown). This prevents the AI from sending malformed data. It also keeps logs clean if something goes wrong.
  • Security (Prompt Injection & Malicious Tools). MCP is powerful, but be cautious. Treat tools as potentially dangerous operations. For example, an LLM might try to combine multiple tool calls in a way that exfiltrates data. Always review which tools an AI can invoke and under what context. Research has shown that MCP can be vulnerable to prompt-injection or sneaky tool replacement attacks, so monitor usage carefully. If you’re connecting to third-party APIs, ensure you’re not leaking tokens or sensitive info.
  • Use HTTPS and Authentication for Remote. When running servers on the internet, always use SSL/TLS. Implement standard OAuth or API key authentication for your endpoints. (For example, Cloudflare Workers provide a turnkey OAuth handler for you.) MCP itself assumes you’ll use OAuth-like flows to let users sign in and grant permissions, so leverage those rather than writing your own ad-hoc token system.
  • Handle Errors and Reconnection. Network glitches happen. The MCP SDK transports have retry modes, but design your client to handle disconnects or server timeouts gracefully. Log errors on both sides. The Claude Desktop guide recommends tailing the MCP logs if tools fail – you should similarly monitor your server’s output and the client’s logs.
  • Keep Spec Versions and SDKs Updated. MCP is evolving rapidly. For example, the older SSE transport is being phased out in favor of the Streamable HTTP transport. Make sure you use the latest SDK releases and check the MCP spec updates. Also pay attention to versioning fields (nameversion) in Client and McpServer for compatibility.
  • Testing. Before connecting a powerful LLM (like GPT-4) to your server, test tools with simple inputs and offline prompts. Tools should fail safely. Use the MCP Inspector tool (npx @modelcontextprotocol/inspector) to list and test tools manually over HTTP.

Useful References and Next Steps

  • Official Docs: The Model Context Protocol documentation covers the spec and has tutorials (including local vs. remote server setup). Anthropic’s README lists many reference servers and usage tips.
  • MCP GitHub: The typescript-sdk repo has examples and detailed API info; we cited its Quick Start above.
  • Articles & Blogs: The Cloudflare MCP blog walks through deploying to Workers. Marc Nuri’s JavaScript tutorial shows client-side code and LangChain integration. Microsoft’s DevBlogs and Azure samples illustrate MCP in C# and TS.
  • Community Servers: Check out the mcp-servers repo for ready-made servers (Filesystem, GitHub, SQL, etc.) you can adapt.

By following these guidelines and examples, you can bring the power of MCP to your JavaScript projects. MCP servers let your AI assistants do things in your apps and data environments in a secure, standardized way, moving from mere chatbots to truly helpful agents.

Top comments (0)