ToolPlex
Guides

Tutorial: Build a Custom Tool

Build a private MCP server, publish it to your registry, and use it in chat.

Tutorial: Build a Custom Tool

In this tutorial, you'll build a custom tool that gives your AI agent access to internal product data, publish it to your organization's private registry, and use it in a chat conversation.

By the end, your team will be able to ask the AI questions like "What's the stock level for SKU-4810?" and get real answers from your systems.

What you'll need

  • ToolPlex Desktop installed and signed in
  • An organization with Admin or Owner access
  • Node.js 18 or later
  • Your Scope ID and API key (both in Org Settings)

Step 1: Clone the template

Start from our example project:

git clone https://github.com/toolplex/private-tool-example.git my-inventory-tool
cd my-inventory-tool
npm install

The template gives you a working MCP server with a product catalog — search, detail, and low-stock tools with mock data. You'll replace it with your own logic.

Step 2: Define your tools

Open src/index.ts and replace the example tools with your own. Here's a product lookup tool:

import { z } from "zod";

server.registerTool(
  "check_stock",
  {
    description: "Check inventory levels for a product",
    inputSchema: {
      query: z.string().describe("Product name or SKU"),
    },
  },
  async ({ query }) => {
    const results = await yourApi.searchProducts(query);

    if (results.length === 0) {
      return { content: [{ type: "text", text: "No products found." }] };
    }

    const summary = results.map(p =>
      `${p.name} (${p.sku}): ${p.stock_on_hand} units in stock`
    ).join("\n");

    return { content: [{ type: "text", text: summary }] };
  }
);

A few guidelines for good tools:

  • Keep them read-only when possible. AI agents can call tools repeatedly, so side-effect-free operations are safest.
  • Return clear text. The AI reads the output to form its response, so structured plain text works better than raw JSON.
  • Use descriptive names and descriptions. The AI uses these to decide which tool to call and when.

Step 3: Connect to your data

How you fetch data is up to you. Common patterns:

  • REST API — Call your internal service with fetch or a client library
  • Database — Query directly with a driver like pg, mysql2, or better-sqlite3
  • File system — Read from CSV exports, JSON files, or local databases

Authenticating with environment variables

Never hardcode credentials in your tool. Use environment variables and validate them at startup so the server fails fast with a clear error if something is missing:

const API_URL = process.env.MY_API_URL;
const API_TOKEN = process.env.MY_API_TOKEN;

if (!API_URL) throw new Error("MY_API_URL environment variable is required");
if (!API_TOKEN) throw new Error("MY_API_TOKEN environment variable is required");

Then use them when making requests:

async function fetchFromApi(path: string) {
  const res = await fetch(`${API_URL}${path}`, {
    headers: {
      Authorization: `Bearer ${API_TOKEN}`,
      Accept: "application/json",
    },
  });
  if (!res.ok) throw new Error(`API error: ${res.status}`);
  return res.json();
}

Setting environment variables

Set these in two places:

  • Locally — Create a .env file or export vars in your shell for development
  • In ToolPlex — Go to Org Settings > Environment variables to add them for cloud execution. All organization environment variables are automatically available to your cloud tools at runtime.

See Environment variables for details on managing org-level secrets.

Step 4: Update package.json

Replace the package name with your organization's scope:

{
  "name": "@YOUR_SCOPE_ID/inventory",
  "version": "1.0.0",
  "toolplex": {
    "server_name": "Inventory Lookup",
    "description": "Check product stock levels across warehouses",
    "keywords": ["inventory", "stock", "warehouse"]
  }
}

Find your Scope ID in the Org Settings panel in ToolPlex Desktop.

Step 5: Test locally

Run your tool to make sure it starts without errors:

npm run build
node dist/index.js

The MCP server communicates over stdio, so you won't see output in the terminal — it's waiting for input from an AI agent. If it starts without crashing, you're good.

Step 6: Publish

Log in to your organization's private registry and publish:

npm login --registry=YOUR_REGISTRY_URL
npm publish --registry=YOUR_REGISTRY_URL

Use the credentials from your Org Settings panel. Find your registry URL there as well.

Your tool will appear in ToolPlex Desktop within about 30 minutes.

Step 7: Install and use

  1. In ToolPlex Desktop, go to the Servers panel
  2. Click the Private tab
  3. Find your tool and click Install

Now open a chat and try it:

"What's the current stock for athletic socks?"

The AI will call your check_stock tool and return the results from your system.

Step 8: Add more tools

Most useful tools expose 3-6 related capabilities. For an inventory system, you might add:

  • search_products — Find products by name, SKU, or category
  • check_stock — Stock levels across warehouses
  • get_low_stock_items — Products below reorder point
  • get_inventory_summary — High-level metrics

Each tool is a separate server.registerTool() call in your src/index.ts.

Publishing updates

When you add features or fix bugs, bump the version and publish again:

npm version patch
npm publish --registry=YOUR_REGISTRY_URL

Team members get the update automatically on their next install.

Next steps