sample-mcp
by JeonJunYeong
README.md
# sample-mcp
NestJS + TypeScript MCP (Model Context Protocol) server boilerplate.
This project is intentionally small. Use it as a starting point when you want to add your own MCP tools and serve them through either stdio or Streamable HTTP.
## Features
- NestJS dependency injection for MCP tools
- MCP SDK `Server` integration
- stdio transport for MCP clients such as Claude Desktop and Cursor
- Streamable HTTP transport for local HTTP testing
- Zod-based input validation
- ESLint + Prettier setup for TypeScript
## Project Structure
```text
src/
main.ts # Transport bootstrap: stdio or HTTP
app.module.ts # Root Nest module
config/
app.config.ts # Environment config
mcp/
mcp.module.ts # MCP Nest module
mcp.service.ts # MCP server and request handlers
http/
mcp-http.controller.ts # POST /mcp Streamable HTTP endpoint
tools/
base.tool.ts # Base class for tools
tool.registry.ts # Tool list and execution registry
tools.module.ts # Nest providers for tools
ping/
ping.dto.ts # Zod schema and output type
ping.tool.ts # Example tool implementation
```
## Setup
```powershell
pnpm install
```
Copy `.env.example` to `.env` if you want local overrides.
```env
MCP_SERVER_NAME=sample-mcp
MCP_SERVER_VERSION=1.0.0
LOG_LEVEL=log
NODE_ENV=development
TRANSPORT=stdio
PORT=3000
```
## Run
### stdio mode
```powershell
pnpm start
```
Use stdio mode when another MCP client launches this server process.
### HTTP mode
```powershell
pnpm run start:http
```
The MCP endpoint is:
```text
POST http://localhost:3000/mcp
```
HTTP requests must include:
```http
Accept: application/json, text/event-stream
Content-Type: application/json
```
## Test With HTTP
List tools:
```powershell
$body = @{
jsonrpc = "2.0"
id = 1
method = "tools/list"
params = @{}
} | ConvertTo-Json -Depth 10
Invoke-RestMethod `
-Method Post `
-Uri "http://localhost:3000/mcp" `
-ContentType "application/json" `
-Headers @{ Accept = "application/json, text/event-stream" } `
-Body $body
```
Call the sample `ping` tool:
```powershell
$body = @{
jsonrpc = "2.0"
id = 2
method = "tools/call"
params = @{
name = "ping"
arguments = @{
message = "hello"
}
}
} | ConvertTo-Json -Depth 10
Invoke-RestMethod `
-Method Post `
-Uri "http://localhost:3000/mcp" `
-ContentType "application/json" `
-Headers @{ Accept = "application/json, text/event-stream" } `
-Body $body
```
## Add A New MCP Tool
1. Create a folder under `src/mcp/tools/<tool-name>/`.
2. Create a Zod schema file, for example `<tool-name>.dto.ts`.
3. Create a tool class that extends `BaseTool`.
4. Add the tool class to `ToolsModule.providers`.
5. Inject it into `ToolRegistry` and add it to `registerTools([...])`.
Minimal tool shape:
```typescript
import { Injectable } from '@nestjs/common';
import type { CallToolResult, Tool } from '@modelcontextprotocol/sdk/types.js';
import { BaseTool } from '../base.tool';
@Injectable()
export class MyTool extends BaseTool {
get definition(): Tool {
return {
name: 'my-tool',
description: 'Describe what this tool does.',
inputSchema: {
type: 'object',
properties: {
input: { type: 'string' },
},
required: ['input'],
},
};
}
execute(args: Record<string, unknown>): Promise<CallToolResult> {
return Promise.resolve(this.success({ args }));
}
}
```
## Quality Checks
This boilerplate uses ESLint 8 with `.eslintrc.cjs` for broad editor and CLI compatibility.
```powershell
pnpm lint
pnpm run lint:fix
pnpm exec tsc --noEmit
pnpm run build
```
This server cannot be deployed
Maintenance
ActivityInactive
ResponsivenessNo issues