---
title: "Build a small MCP server in TypeScript"
url: "https://lookvalid.com/blog/tutorial/build-an-mcp-server-typescript.md"
canonical_url: "https://lookvalid.com/blog/tutorial/build-an-mcp-server-typescript"
last_updated: "2026-10-22"
type: "how-to"
summary: "Write a minimal MCP server in TypeScript with one tool that wraps a LookValid lookup over REST, using the official SDK as documented."
related: ["https://lookvalid.com/docs/mcp.md", "https://lookvalid.com/products/phone.md", "https://lookvalid.com/docs/quickstart.md", "https://lookvalid.com/glossary/mcp.md"]
---

# Build a small MCP server in TypeScript

Write a minimal MCP server in TypeScript with one tool that wraps a LookValid lookup over REST, using the official SDK as documented.

An MCP server lets an AI client call a function you define. This tutorial builds the smallest useful one in TypeScript: a single tool that wraps the LookValid phone lookup over REST. We ran the code against the official SDK before publishing it, and the version is named below.

## What an MCP tool is

The Model Context Protocol lets servers expose tools that language models can invoke. Each tool has a unique name, a description and an `inputSchema` in JSON Schema; clients discover tools with a `tools/list` request and run one with `tools/call` [1]. Tool names should be 1 to 128 characters of letters, digits, underscore, hyphen or dot [1].

Two kinds of failure exist. A protocol error, such as an unknown tool, is a JSON-RPC error. A tool execution error, such as an API failure, is a normal result with `isError: true` so the model can read it and adjust [1]. Your tool should use the second kind when the lookup fails.

## Set up the SDK

The official TypeScript SDK is the package `@modelcontextprotocol/sdk`, and it needs `zod` installed beside it as a peer dependency [2]. We ran the server below against SDK version 1.32.1 and zod 4.

Install the SDK and zod

```bash
npm install @modelcontextprotocol/sdk zod
```

## Write the server

The SDK builds a server with `McpServer` and connects it to a transport such as stdio [2]. The tool below registers one tool with `registerTool` and a zod `inputSchema`, connects over standard input and output with `StdioServerTransport`, and calls our REST endpoint with `fetch`. Because stdout carries the protocol, the server logs with `console.error`; one stray `console.log` would corrupt the stream.

A minimal server with one tool

```ts
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import * as z from 'zod/v4';

const server = new McpServer({ name: 'phone-check', version: '1.0.0' });

server.registerTool(
  'validate_phone',
  {
    description: 'Check a phone number against its numbering plan and return E.164, country and number type.',
    inputSchema: { phone: z.string() },
  },
  async ({ phone }) => {
    const res = await fetch('https://YOUR_API_HOST/v1/phone', {
      method: 'POST',
      headers: {
        Authorization: 'Bearer ' + process.env.LOOKVALID_API_KEY,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({ phone }),
    });
    const body = await res.json();
    if (!res.ok) {
      return { content: [{ type: 'text', text: 'LookValid error: ' + body.error.code }], isError: true };
    }
    return { content: [{ type: 'text', text: JSON.stringify(body.found ? body.data : { found: false, reason: body.reason }) }] };
  },
);

async function main() {
  const transport = new StdioServerTransport();
  await server.connect(transport);
  console.error('phone-check MCP server running on stdio');
}
main();
```

The handler returns a `content` array with a text item, which is the result shape in the specification [1]. On failure it sets `isError: true`, the tool execution error described above [1].

## What the tool returns

The pieces of the tool and where each is defined

| Piece | Value in this server | Defined by |
| --- | --- | --- |
| Tool name | validate_phone | MCP specification naming rules |
| Input | one string, phone | zod shape converted to JSON Schema by the SDK |
| Success result | JSON text of the lookup data | LookValid phone response |
| Lookup not found | found false with a reason, not an error | LookValid: a normal free answer |
| Failure | isError true with the API error code | MCP tool execution error |

The REST call can be tested on its own before you wrap it.

The REST request the tool makes

```bash
curl -X POST https://YOUR_API_HOST/v1/phone \
  -H "Authorization: Bearer $LOOKVALID_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"phone":"+14155552671"}'
```

## Run it and connect a client

1. Save the file as `server.ts` and set `LOOKVALID_API_KEY` in the environment of the process that launches it.
2. Add the command that starts it to your MCP client's server list, in whatever configuration format that client uses.
3. Ask the client to validate a number and watch the tool call.

The specification advises keeping a human in the loop with the ability to deny tool calls, so leave your client's confirmation prompts on [1]. You do not have to write any of this to use LookValid from an AI client: our hosted server exposes every live lookup as a tool, described in the [MCP docs](https://lookvalid.com/docs/mcp.md). To call the REST endpoint from your own code, start with the [quickstart](https://lookvalid.com/docs/quickstart.md) or the [phone product page](https://lookvalid.com/products/phone.md).

## Sources

1. [Model Context Protocol specification 2026-07-28: Tools](https://modelcontextprotocol.io/specification/2026-07-28/server/tools), read 2026-10-19
2. [MCP TypeScript SDK: README](https://github.com/modelcontextprotocol/typescript-sdk/tree/v1.x), read 2026-10-19

By LookValid engineering. Published 2026-10-19, updated 2026-10-19.

## Related

- [MCP server](https://lookvalid.com/docs/mcp.md)
- [Phone Numbering-Plan Validation API](https://lookvalid.com/products/phone.md)
- [Quickstart](https://lookvalid.com/docs/quickstart.md)
- [What is MCP (Model Context Protocol)?](https://lookvalid.com/glossary/mcp.md)
