Hugo | MCP API
Give Feedback

Server Examples

Updated on March 30, 2026

Code examples for building MCP servers that connect to Hugo.

This guide uses TypeScript examples, but the concepts apply to any language. See the Quickstart for SDK links in other languages.

Demo Project

Want to get started quickly? Clone our demo MCP server:

git clone https://github.com/crisp-im/crisp-mcp-demo.git
cd crisp-mcp-demo
npm ci
npm run dev

The demo includes get_user, get_order, and get_product tools with mock data. You can also use the hosted version at https://crisp-mcp-demo.fly.dev/mcp.


Basic MCP Server

Here's a minimal MCP server using the official TypeScript SDK:

import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
import { z } from "zod";
import http from "http";

const server = new McpServer({
  name: "my-company-tools",
  version: "1.0.0",
  description: "Access the Acme store database. Use it to retrieve customer orders, get product information, and check inventory levels."
});

// Define a tool that Hugo can call
server.tool(
  "get_customer",
  "Retrieve customer information by email",
  {
    email: z.string().email().describe("Customer email address")
  },
  async ({ email }) => {
    const customer = await fetchCustomerFromDatabase(email);
    
    return {
      content: [{
        type: "text",
        text: JSON.stringify(customer, null, 2)
      }]
    };
  }
);

// Create HTTP server
const httpServer = http.createServer(async (req, res) => {
  const transport = new StreamableHTTPServerTransport({
    sessionIdGenerator: () => crypto.randomUUID()
  });
  
  await server.connect(transport);
  await transport.handleRequest(req, res);
});

httpServer.listen(3000);

Product Search

Allow Hugo to search your product catalog:

server.tool(
  "search_products",
  "Search for products by name, category, or keywords",
  {
    query: z.string().describe("Search query"),
    category: z.string().optional().describe("Filter by category"),
    limit: z.number().default(5).describe("Maximum results to return")
  },
  async ({ query, category, limit }) => {
    const products = await db.products.search({
      query,
      category,
      limit
    });

    return {
      content: [{
        type: "text",
        text: JSON.stringify(products, null, 2)
      }]
    };
  }
);

Order Information

Let Hugo retrieve order details for customers:

server.tool(
  "get_order",
  "Get order details by order ID or customer email",
  {
    orderId: z.string().optional().describe("Order ID"),
    email: z.string().email().optional().describe("Customer email")
  },
  async ({ orderId, email }) => {
    let order;

    if (orderId) {
      order = await db.orders.findById(orderId);
    } else if (email) {
      order = await db.orders.findLatestByEmail(email);
    }

    if (!order) {
      return {
        content: [{ type: "text", text: "Order not found." }],
        isError: true
      };
    }

    return {
      content: [{
        type: "text",
        text: JSON.stringify({
          id: order.id,
          status: order.status,
          items: order.items,
          total: order.total,
          shippingDate: order.shippingDate
        }, null, 2)
      }]
    };
  }
);

Perform Actions

Enable Hugo to take actions on behalf of customers:

server.tool(
  "cancel_order",
  "Cancel an order if it has not been shipped yet",
  {
    orderId: z.string().describe("Order ID to cancel"),
    reason: z.string().optional().describe("Cancellation reason")
  },
  async ({ orderId, reason }) => {
    const order = await db.orders.findById(orderId);

    if (!order) {
      return {
        content: [{ type: "text", text: "Order not found." }],
        isError: true
      };
    }

    if (order.status === "shipped") {
      return {
        content: [{ type: "text", text: "Cannot cancel: order already shipped." }],
        isError: true
      };
    }

    await db.orders.cancel(orderId, reason);

    return {
      content: [{
        type: "text",
        text: `Order ${orderId} has been cancelled.`
      }]
    };
  }
);

Create Support Tickets

Let Hugo escalate issues to your support team:

server.tool(
  "create_support_ticket",
  "Create a support ticket for escalation",
  {
    subject: z.string().describe("Ticket subject"),
    description: z.string().describe("Detailed description"),
    priority: z.enum(["low", "medium", "high"]).default("medium")
  },
  async ({ subject, description, priority }) => {
    const ticket = await supportSystem.createTicket({
      subject,
      description,
      priority
    });

    return {
      content: [{
        type: "text",
        text: `Ticket #${ticket.id} created. A support agent will follow up shortly.`
      }]
    };
  }
);

Best Practices

Server Description

Always provide a clear description when creating your MCP server. This helps Hugo understand when to use your server:

const server = new McpServer({
  name: "acme-store",
  version: "1.0.0",
  description: "Access the Acme store database. Use it to retrieve customer orders, get product information, and check inventory levels."
});

Tool Design

  • Use clear, descriptive names: get_order_status is better than gos
  • Provide detailed descriptions: Help Hugo understand when to use each tool
  • Define precise schemas: Use Zod to validate inputs
  • Handle errors gracefully: Return helpful error messages

Performance

  • Keep responses fast: Hugo waits for your server to respond
  • Use caching where appropriate to reduce latency
Information: MCP connections have a default timeout. If your tool needs to perform long-running operations, consider returning a reference ID and providing a separate tool to check the status.

Next Steps