Build / AI /

Model Context Protocol

Standardize AI agent tool integrations and resource access using Anthropic open-standard Model Context Protocol.

TL;DR

  1. Standardize tool and resource integrations across models using the mcp-protocol.
  2. Implement lightweight local server communication over the stdio-transport.
  3. Expose executable tools, contextual resources, and reusable prompt-templates.

MCP Server Architecture

    Server Initialization

    Create an MCP server instance with identity metadata.

    import {
      McpServer,
    } from '@modelcontextprotocol/sdk/server/mcp.js';
    import {
      StdioServerTransport,
    } from '@modelcontextprotocol/sdk/server/stdio.js';
    
    const server = new McpServer({
      name: 'inventory-server',
      version: '1.0.0',
    });
    Register Executable Tool

    Expose typed tool endpoint with Zod schema validation.

    import { z } from 'zod';
    server.tool(
      'get_stock',
      { sku: z.string() },
      async ({ sku }) => ({
        content: [{ type: 'text', text: `SKU: ${sku}` }],
      })
    );
    Stdio Transport Connect

    Connect server to standard input and output streams.

    const transport = new StdioServerTransport();
    await server.connect(transport);

Resources And Prompts

    Expose Static Resource

    Provide read-only contextual document identified by URI.

    server.resource(
      'schema',
      'schema://database/main',
      async uri => ({
        contents: [{
          uri: uri.href,
          text: 'CREATE TABLE users (id INT, email TEXT);',
        }],
      })
    );
    Reusable Prompt Template

    Expose standardized prompt workflows to MCP clients.

    server.prompt(
      'review_code',
      { code: z.string() },
      ({ code }) => ({
        messages: [{
          role: 'user',
          content: { type: 'text', text: `Code: ${code}` },
        }],
      })
    );
    Dynamic URI Template

    Route parameterized resource URIs dynamically.

    import {
      ResourceTemplate,
    } from '@modelcontextprotocol/sdk/server/mcp.js';
    const tmpl = new ResourceTemplate(
      'users://{id}/profile',
      { list: undefined }
    );
    server.resource(
      'user-profile',
      tmpl,
      async (u, { id }) => ({
        contents: [{ uri: u.href, text: `User ${id}` }],
      })
    );

MCP Client Consumption

    Client Connection Setup

    Establish client link to local MCP server process.

    import {
      Client,
    } from '@modelcontextprotocol/sdk/client/index.js';
    import {
      StdioClientTransport,
    } from '@modelcontextprotocol/sdk/client/stdio.js';
    
    const transport = new StdioClientTransport({
      command: 'node',
      args: ['./dist/server.js'],
    });
    const client = new Client(
      { name: 'agent-client', version: '1.0' }
    );
    await client.connect(transport);
    List Available Tools

    Query server for active tools and their JSON schemas.

    const { tools } = await client.listTools();
    console.log(`Discovered ${tools.length} MCP tools`);
    Invoke Remote Tool

    Dispatch tool execution call and receive content payload.

    const result = await client.callTool({
      name: 'get_stock',
      arguments: { sku: 'WIDGET-01' },
    });
    console.log(result.content[0].text);

Production MCP Hygiene

    Stderr Logging Rule

    Redirect application logs to stderr to avoid stream corruption.

    console.error('[MCP DEBUG] Processing tool execution');
    // NEVER use console.log in Stdio mode
    // It corrupts JSON-RPC stdout communication
    Transport Error Recovery

    Handle server process disconnection and automatic restart.

    transport.onclose = () => {
      logger.warn('MCP closed. Reconnecting...');
      reconnectClient();
    };
    Security Sandboxing

    Validate client path requests against restricted directory.

    function safePath(userPath: string, rootDir: string) {
      const resolved = path.resolve(rootDir, userPath);
      if (!resolved.startsWith(rootDir)) {
        throw new Error('Access denied');
      }
      return resolved;
    }

Tips

  1. Use the official @modelcontextprotocol/sdk to build type-safe MCP servers with automatic JSON-RPC protocol compliance.
  2. Organize local MCP servers to communicate over standard input and output streams using stdio-transport for sandboxing.

Warnings

  1. Sanitize all inputs received from MCP clients using zod-validation because tool parameters can execute unauthorized local actions.
  2. Do not write debug logs to standard output in stdio-mode because unformatted text corrupts JSON-RPC protocol streams.

In Practice

FAQ