Skip to content

MCP Development Guide

A practical guide from planning and design through implementation to publishing MCP servers.

About This Document

This is a practical guide for not just "using" MCP servers but "creating" them. Based on experience building 7 MCP servers, we have systematized the knowledge gained—including decision criteria at the planning stage, architectural patterns during design, best practices for implementation, and the workflow for npm publishing.

The goal is to make the decision of "should this really be an MCP?" before building, and if the answer is yes, to enable you to build a high-quality server in the shortest time possible.

Prerequisites

Before reading this document, it is desirable to have an understanding of the following:

Decision: Should This Be MCP?

Decision Flow

Decision Criteria Checklist

Use the following checklist to systematically evaluate whether building an MCP is the right choice for your use case.

markdown
## MCP Development Decision

### Conditions When MCP Should Be Built (Consider building if all are Yes)
- [ ] Access to external data sources or APIs is required
- [ ] Official MCP does not exist
- [ ] Official CLI is insufficient (complex authentication, missing features, etc.)
- [ ] Used repeatedly (not just once)

### Conditions When MCP Should NOT Be Built (Use alternative if any is Yes)
- [ ] Team internal guidelines → Skill
- [ ] Static knowledge/principles → Skill
- [ ] Official CLI is sufficient → CLI + Skill
- [ ] Simple one-time processing → Script

See MCP vs Skills Selection Guide for details

MCP Design Based on "Authoritative Reference Sources"

Core Philosophy

The greatest value of MCP is providing AI with structured access to authoritative information sources.

MCP Value = "Authoritative Reference Sources" × Structured × Accessibility

Information generated by AI alone → Risk of hallucination
Information sourced from "authoritative reference sources" → Accurate, verifiable

Four-Layer Hierarchy of Reference Sources and MCP

LayerReference SourceMCP ExampleBuild Priority
1International standards / Regulationsrfcxml-mcp, pdf-spec-mcpHighest
2Industry standards / De factow3c-mcp, (OpenAPI MCP)High
3Organization / Project guidelines— (handled by Skill)
4Best practices— (handled by Skill)

Important: Layers 1 and 2 are suited for MCP, while layers 3 and 4 are suited for Skills.

See Taxonomy of "Authoritative Reference Sources" for details

Design Phase

Architecture Patterns

Based on experience building MCPs, we recommend the following three architecture patterns.

Pattern 1: Local Data Type

Data is embedded in the package and operates without external communication.

CharacteristicDescription
CommunicationNone (offline operation)
DataEmbedded in package
AdvantagesFast, no authentication required, privacy
Use Casesepsg-mcp, pdf-spec-mcp

Pattern 2: External API Type

Calls external APIs and returns structured results.

CharacteristicDescription
CommunicationHTTP requests to external APIs
DataFetched in real-time
AdvantagesAlways up-to-date, handles large-scale data
Use Casesrfcxml-mcp (RFC Editor XML), w3c-mcp

Pattern 3: Model Loading Type

Loads ML models and performs inference.

CharacteristicDescription
CommunicationNone (local inference)
DataEmbedded in model
AdvantagesNo external dependencies, fast inference (after warmup)
Use Casesxcomet-mcp-server

Tool Design Principles

1. Single Responsibility

One tool = One clear responsibility.

typescript
// ✅ Good example: Clear responsibilities
get_rfc_structure    // Section hierarchy only
get_requirements     // MUST/SHOULD requirements only
validate_statement   // Compliance verification only

// ❌ Bad example: Ambiguous responsibilities
get_rfc_everything   // All-in-one

2. Progressive Detail Discovery

Tool design that allows information retrieval in the order: overview → details.

typescript
// Step 1: Understand structure
get_rfc_structure(6455)          // → List of sections

// Step 2: Deep dive into specific section
get_section(6455, "5.2")         // → Section content

// Step 3: Extract requirements
get_requirements(6455, "MUST")   // → MUST requirements only

3. Input Validation

Implement validation for all tool inputs.

typescript
const schema = {
  type: 'object',
  properties: {
    rfc: {
      type: 'number',
      minimum: 1,
      maximum: 99999,
      description: 'RFC number'
    },
    level: {
      type: 'string',
      enum: ['MUST', 'SHOULD', 'MAY'],
      description: 'Requirement level'
    }
  },
  required: ['rfc']
};

For security details, see MCP Security section MCP05 (Command Injection)

4. Response Design

Provide both structured output and human-readable output.

typescript
// Switch via response_format parameter
tool: get_requirements
params:
  rfc: 6455
  response_format: "json"     // → Structured data
  // or
  response_format: "markdown" // → Human-readable Markdown

Tool Count Guidelines

The following guidelines provide recommended ranges for tool count based on MCP complexity and scope.

Small MCP: 3-5 tools (single data source)
Medium MCP: 5-10 tools (multiple views)
Large MCP: 10-15 tools (3-tier structure)

Example: pdf-reader-mcp (15 tools)
├── Basic Operations Layer (5): read_text, read_images, search_text, ...
├── Structure Inspection Layer (5): inspect_structure, inspect_tags, ...
└── Validation/Analysis Layer (5): validate_tagged, validate_metadata, ...

Implementation Phase

Technology Stack

ComponentRecommendedRationale
LanguageTypeScriptType safety, MCP SDK support
SDK@modelcontextprotocol/sdkOfficial SDK
Buildtsup / esbuildFast builds
TestingVitestTypeScript friendly
Package ManagementnpmStandard for MCP distribution

Project Structure

my-mcp/
├── src/
│   ├── index.ts              # Entry point
│   ├── server.ts             # MCP server definition
│   ├── tools/                # Tool implementations
│   │   ├── search.ts
│   │   ├── get-detail.ts
│   │   └── validate.ts
│   ├── data/                 # Data and parsers
│   │   ├── loader.ts
│   │   └── parser.ts
│   └── utils/                # Utilities
│       └── format.ts
├── tests/
│   ├── unit/
│   └── e2e/
├── package.json
├── tsconfig.json
├── vitest.config.ts
└── README.md

Implementation Checklist

markdown
## Before Implementation
- [ ] Define tool list and schemas
- [ ] Determine input validation rules
- [ ] Design response format (JSON / Markdown)
- [ ] Decide on error handling policy

## During Implementation
- [ ] Review OWASP MCP Top 10 (especially MCP01, MCP05)
- [ ] Implement input validation for all tools
- [ ] Implement structured error responses
- [ ] Ensure logs don't contain sensitive information

## After Implementation
- [ ] Create unit tests (80%+ coverage)
- [ ] Create E2E tests (main flows)
- [ ] Create README.md (tool list, usage examples)
- [ ] Create CHANGELOG.md

Testing Phase

Test Strategy

Test Results (Reference Values)

MCPUnit TestsE2ETotal
pdf-reader-mcp39146185
rfcxml-mcp
epsg-mcp

Importance of E2E Tests

The interface of an MCP server is everything—"tool call → response". Running E2E tests via actual MCP protocol is critical for quality assurance.

typescript
// E2E test example
describe('rfcxml-mcp E2E', () => {
  it('should get RFC structure', async () => {
    const result = await callTool('get_rfc_structure', { rfc: 6455 });
    expect(result.sections).toBeDefined();
    expect(result.sections.length).toBeGreaterThan(0);
  });

  it('should extract MUST requirements', async () => {
    const result = await callTool('get_requirements', {
      rfc: 6455,
      level: 'MUST'
    });
    expect(result.requirements.length).toBeGreaterThan(0);
  });
});

Publishing Phase

npm Publishing Flow

package.json Design

A well-structured package.json is essential for npm publishing and defining your MCP's configuration and dependencies.

json
{
  "name": "@shuji-bonji/my-mcp",
  "version": "0.1.0",
  "description": "MCP server for ...",
  "type": "module",
  "bin": {
    "my-mcp": "dist/index.js"
  },
  "files": ["dist"],
  "keywords": ["mcp", "model-context-protocol"],
  "engines": {
    "node": ">=18"
  },
  "scripts": {
    "build": "tsup src/index.ts --format esm",
    "test": "vitest",
    "prepublishOnly": "npm run build && npm test"
  }
}

Versioning Policy

Version ChangeTimingExample
patch (0.0.x)Bug fixes, documentation updates0.1.0 → 0.1.1
minor (0.x.0)New tools added, features enhanced0.1.1 → 0.2.0
major (x.0.0)Breaking changes, tool schema changes0.9.0 → 1.0.0

README.md Structure

A good README determines first impressions of users. We recommend the following structure:

markdown
# my-mcp

> One-line description

## Features

## Quick Start

## Available Tools

| Tool | Description |
|------|-------------|

## Examples

## Configuration

## Development

## License

Lessons Learned from Built MCPs

Lesson 1: Data Preprocessing Determines Quality

In rfcxml-mcp, instead of directly parsing RFC Editor XML, we designed it to structure the data first before passing it to tools. This significantly improved response speed and accuracy.

Lesson 2: response_format Should Be Designed From the Start

In pdf-reader-mcp, we added the response_format parameter partway through. We should have designed it from the beginning to output both "JSON (for programs) and Markdown (for humans)".

Lesson 3: Tool Granularity Should Enable Progressive Detail Discovery

The 9 tools in epsg-mcp were designed to follow a progressive information retrieval flow: search → detail → recommend → validate. This allows users to drill down only to the depth they need, optimizing token consumption.

Lesson 4: E2E Tests From the Beginning

The 185 tests in pdf-reader-mcp (146 of which are E2E) serve as proof of quality. E2E tests guarantee that the tool "works as expected via the MCP protocol", providing confidence during refactoring.

Lesson 5: Model Loading Type Requires Careful Initialization Strategy

xcomet-mcp-server uses persistent ML model loading. The first startup is slow, but subsequent inferences are fast. Progress display during startup and timeout settings are critical.

MCP Coverage by Development Phase

Current MCPs mainly cover the "implementation" phase. The direction of future coverage expansion is as follows, visualized in the diagram below.

See Development Phases × MCP Support for details

Released under the MIT License.