Leanpub Header

Skip to main content

The Model Context Protocol (MCP) in Practice

Building, Integrating, and Scaling Custom Tool Servers for AI Agents

A hands-on guide to designing, building, testing, and deploying secure stdio and SSE MCP servers in Python and TypeScript (447 manuscript pages).

Minimum price

$19.99

$24.99

You pay

Author earns

$

Also available for 1 book credit with a Reader Membership

PDF
About

About

About the Book

The Model Context Protocol (MCP) in Practice is a structured, hands-on guide to building custom MCP servers that securely connect large language models to real tools, live data, and organizational systems.

The content is organized around the protocol itself: the JSON-RPC 2.0 wire format, stdio and SSE transports, the initialize/initialized handshake, and the three server primitives (tools, resources, and prompt templates). It then builds real servers in both Python and TypeScript, hardens them, and takes them all the way to Docker-packaged, SSE-hosted production deployment.

Author

About the Author

Yohan Rodriguez

Yohan is a Senior Full-Stack Software Engineer with extensive experience delivering scalable, end-to-end software solutions across web, enterprise, and cloud-based environments. He specializes in architecting robust platforms, modernizing legacy systems, driving cloud transformation efforts, and building integration-heavy applications that support critical business workflows. He is recognized for translating complex requirements into reliable, maintainable, and high-value solutions across industries such as insurance, cybersecurity, and professional services.

Known for combining strong technical execution with a practical business mindset, he has contributed to projects from concept and design through production delivery and long-term support. His experience includes collaborating with cross-functional teams, improving development workflows, solving complex technical challenges, and helping organizations deliver dependable software products that adapt to changing business needs. He brings a balanced approach to engineering that values quality, efficiency, and continuous improvement.

Contents

Table of Contents

  • Preface i
  • 1 The MCP Landscape: Why Protocol Beats Integration 3
    • 1.1 The N-by-M Integration Problem 3
    • 1.2 What a Protocol Buys You 5
    • 1.3 The Three Primitives at a Glance 6
    • 1.4 Where MCP Fits in the Stack 7
    • 1.5 MCP, Function Calling, and Framework Tools 8
    • 1.6 The MCP Client Ecosystem 9
    • 1.7 The Four Servers You Will Build 9
    • 1.8 Should You Use MCP at All? 10
    • 1.9 Hands-On: Connect Your First Server 11
    • 1.10 What You Will Be Able to Do 13
  • 2 Protocol Internals: JSON-RPC, Transports, and the Handshake 14
    • 2.1 Why the Wire Format Matters 14
    • 2.2 JSON-RPC 2.0: The Foundation 15
    • 2.3 MCP: JSON-RPC With Domain Methods 18
    • 2.4 Transports: Changing the Pipe, Not the Message 19
    • 2.5 The Initialization Handshake 22
    • 2.6 Capability Negotiation 24
    • 2.7 MCP Method Reference 25
    • 2.8 Tools on the Wire 25
    • 2.9 Resources on the Wire 28
    • 2.10 Prompt Templates on the Wire 29
    • 2.11 Error Handling: Four Layers of Failure 31
    • 2.12 Hands-On Lab: Talk to a Server by Hand 33
    • 2.13 A Debugging Checklist by Symptom 36
    • 2.14 Summary and What Comes Next 37
  • 3 The Three Primitives: Tools, Resources, and Prompts 39
    • 3.1 Why Primitive Selection Is a Design Decision 39
    • 3.2 Discovery Before Use 41
    • 3.3 Tools: Callable Actions 41
    • 3.4 Tool Return Values 45
    • 3.5 Tool Design Boundaries 47
    • 3.6 Resources: Readable Context 48
    • 3.7 Resource Content Types 51
    • 3.8 Resource Design Boundaries 51
    • 3.9 Prompts: Reusable Message Workflows 52
    • 3.10 Prompt Design Boundaries 54
    • 3.11 Comparing the Three Primitives 55
    • 3.12 Combining Primitives in One Server 57
    • 3.13 Anti-Patterns 60
    • 3.14 Hands-On Lab: Classify the Capabilities 61
    • 3.15 Beyond the Three Primitives: What This Book Leaves Out 65
    • 3.16 A Note on Versions 66
    • 3.17 Summary and What Comes Next 66
  • 4 Your First MCP Server in Python 69
    • 4.1 Setting Up the Project 69
    • 4.2 The Smallest Useful Server 71
    • 4.3 A Second Tool: Optional Arguments and Bounded Output 72
    • 4.4 How FastMCP Builds the Schema 73
    • 4.5 Adding a Resource 75
    • 4.6 Adding a Prompt Template 76
    • 4.7 Running Over Stdio 77
    • 4.8 A Preview of Client Configuration 80
    • 4.9 Error Handling Done Right 80
    • 4.10 Logging Without Breaking Stdio 82
    • 4.11 The Complete Server 83
    • 4.12 Hands-On Lab: Build, Run, and Break It 86
    • 4.13 Mapping the Implementation Back to the Protocol 87
    • 4.14 Common Beginner Mistakes 87
    • 4.15 Summary and What Comes Next 87
  • 5 Your First MCP Server in TypeScript 90
    • 5.1 Setting Up the Project 91
    • 5.2 The Project Files 91
    • 5.3 The Smallest Useful Server 92
    • 5.4 A Second Tool: Optional Arguments and Bounded Output 94
    • 5.5 How Zod Maps to the Input Schema 95
    • 5.6 Adding a Resource 96
    • 5.7 Adding a Prompt Template 97
    • 5.8 Running Over Stdio 98
    • 5.9 A Preview of Client Configuration 101
    • 5.10 Error Handling in TypeScript 101
    • 5.11 Logging Without Breaking Stdio 103
    • 5.12 The Complete Server 104
    • 5.13 Python and TypeScript, Side by Side 106
    • 5.14 Mapping the Implementation Back to the Protocol 107
    • 5.15 Hands-On Lab: Build, Run, Break, and Compare 108
    • 5.16 Common Beginner Mistakes 108
    • 5.17 Summary and What Comes Next 109
  • 6 Designing Tool Surfaces That Models Actually Use 113
    • 6.1 Valid Is Not the Same as Usable 113
    • 6.2 How Models See Tools 115
    • 6.3 Tool Names: Specific, Action-Oriented, Boring 116
    • 6.4 Descriptions: When to Use, Preconditions, Side Effects, Result 118
    • 6.5 Schema Design: Arguments Are Model Instructions 119
    • 6.6 Field Descriptions Decide Argument Quality 121
    • 6.7 Enums and Constrained Values 122
    • 6.8 Single Rich Tool vs. Multiple Narrow Tools 123
    • 6.9 Idempotency and Retry Safety 126
    • 6.10 Output Design: What the Model Sees After the Call 128
    • 6.11 Error Design: Protocol Error vs. Domain Failure 129
    • 6.12 Testing Tool Surface Quality 130
    • 6.13 Versioning Tool Definitions 132
    • 6.14 Security-Aware Tool Design 133
    • 6.15 Applying the Checklist to the notes-server 134
    • 6.16 Hands-On Lab: Redesign a Bad Tool Surface 136
    • 6.17 The Tool Surface Checklist 138
    • 6.18 Summary and What Comes Next 140
  • 7 Resources: Serving Live Data to Agents 141
    • 7.1 Resources Are the Read Path 142
    • 7.2 Discovery and the Read Flow 143
    • 7.3 The Anatomy of a Resource 144
    • 7.4 URI Design Principles 146
    • 7.5 Static Resources 148
    • 7.6 Templated Resources 149
    • 7.7 Text Resources 152
    • 7.8 Binary and Blob Resources 153
    • 7.9 Live Data Versus Cached Data 153
    • 7.10 Context Efficiency: Return the Slice, Not the World 155
    • 7.11 File-Backed Resources and Path Safety 156
    • 7.12 Resources Versus Tools: Drawing the Line 159
    • 7.13 Resources and Prompt Injection 160
    • 7.14 Resources in the Four Reference Servers 161
    • 7.15 Implementing Resources: Python and TypeScript 162
    • 7.16 Hands-On Lab: Resources for the notes-server 164
    • 7.17 Common Mistakes 166
    • 7.18 The Resource Design Checklist 167
    • 7.19 Summary and What Comes Next 168
  • 8 Prompt Templates: Reusable Context Injection 170
    • 8.1 Prompt Templates Are Workflow Starters 171
    • 8.2 Discovery and Rendering Flow 172
    • 8.3 The Anatomy of a Prompt Template 174
    • 8.4 Prompt Names and Descriptions 175
    • 8.5 Argument Design for Prompts 176
    • 8.6 Rendered Message Sequences 178
    • 8.7 Single-Turn vs. Multi-Turn Templates 179
    • 8.8 Prompt Templates vs. Tools 180
    • 8.9 Prompt Templates vs. Resources 181
    • 8.10 Combining Prompts with Resources and Tools 182
    • 8.11 Prompt Output Structure 184
    • 8.12 Safety and Prompt Injection 185
    • 8.13 Prompt Versioning and Compatibility 186
    • 8.14 Implementing Prompts: Python and TypeScript 187
    • 8.15 Prompt Templates in the Four Reference Servers 191
    • 8.16 Hands-On Lab: Prompts for the notes-server 192
    • 8.17 Common Mistakes 194
    • 8.18 The Prompt Template Design Checklist 195
    • 8.19 Summary and What Comes Next 196
  • 9 Security and Sandboxing 198
    • 9.1 MCP Servers Run With Real Permissions 199
    • 9.2 The Threat Model for MCP Servers 200
    • 9.3 The Defense-in-Depth Model 201
    • 9.4 Capability Minimization 203
    • 9.5 Token and Credential Scoping 205
    • 9.6 Schema Validation Is Necessary but Not Sufficient 206
    • 9.7 Path Allowlists and Filesystem Safety 207
    • 9.8 Shell and Subprocess Safety 211
    • 9.9 SQL and API Injection Prevention 213
    • 9.10 Prompt Injection Through Resource and Tool Output 214
    • 9.11 Output Sanitization and Framing 216
    • 9.12 Dry-Run and Confirmation Workflows 217
    • 9.13 Authentication and Authorization for SSE Servers 218
    • 9.14 Logging and Audit Trails 219
    • 9.15 Process and Container Isolation 220
    • 9.16 Security Review of the notes-server 221
    • 9.17 Security Review of the Four Reference Servers 222
    • 9.18 Hands-On Lab: Harden an Insecure Server 223
    • 9.19 The MCP Security Checklist 225
    • 9.20 Summary and What Comes Next 227
  • 10 Connecting to Claude Code and Other Clients 231
    • 10.1 A Server Is Not Useful Until a Client Can See It 232
    • 10.2 The Client Integration Mental Model 232
    • 10.3 Configuration Anatomy 233
    • 10.4 Connecting to Claude Code 234
    • 10.5 Claude Code Config Examples 235
    • 10.6 Managing and Inspecting Servers in Claude Code 237
    • 10.7 Connecting to Claude Desktop 238
    • 10.8 Cursor and Editor Clients 239
    • 10.9 Zed and Other MCP-Aware Clients 240
    • 10.10 Environment Variables and Secrets 241
    • 10.11 Working Directory and Relative Paths 242
    • 10.12 Python Server Connection Workflow 243
    • 10.13 TypeScript Server Connection Workflow 244
    • 10.14 SSE Server Connection Preview 245
    • 10.15 How to Verify the Connection 246
    • 10.16 Finding the Server's Logs 246
    • 10.17 Troubleshooting by Symptom 247
    • 10.18 Client Differences and Portability 249
    • 10.19 Project-Shared Configuration Policy 250
    • 10.20 Hands-On Lab: Connect Both Servers and Break Them 250
    • 10.21 The Connection Checklist 252
    • 10.22 Summary and What Comes Next 253
  • 11 Building a WordPress MCP Server 254
    • 11.1 Why WordPress Is a Good First Reference Server 255
    • 11.2 Server Capability Overview 255
    • 11.3 WordPress REST API Basics 256
    • 11.4 Authentication with Application Passwords 257
    • 11.5 Project Structure 258
    • 11.6 The WordPress API Client 259
    • 11.7 Tool Surface Design 261
    • 11.8 Implementing the Tools 262
    • 11.9 Resources for WordPress Content 267
    • 11.10 Prompt Templates for Content Workflows 269
    • 11.11 Error Handling and WordPress API Failures 270
    • 11.12 Pagination and Result Limits 271
    • 11.13 Security Review 272
    • 11.14 Local WordPress Test Environment 273
    • 11.15 Client Configuration 274
    • 11.16 Hands-On Lab: Draft, Review, and Revise 276
    • 11.17 Testing Strategy 277
    • 11.18 Extending the Server 278
    • 11.19 Common Mistakes 279
    • 11.20 The WordPress MCP Checklist 279
    • 11.21 Summary and What Comes Next 281
  • 12 Building a GitLab MCP Server 283
    • 12.1 Why GitLab Is the Developer-Workflow Reference Server 284
    • 12.2 Server Capability Overview 285
    • 12.3 GitLab REST API Basics 285
    • 12.4 Authentication with Personal Access Tokens 286
    • 12.5 Project Structure 287
    • 12.6 The GitLab API Client 288
    • 12.7 Tool Surface Design 290
    • 12.8 Implementing the Issue Tools 291
    • 12.9 Implementing the Merge-Request Tools 294
    • 12.10 Implementing the CI/CD Tools 295
    • 12.11 Resources for GitLab Data 299
    • 12.12 Prompt Templates for Developer Workflows 300
    • 12.13 Pagination and Result Limits 302
    • 12.14 Error Handling and GitLab API Failures 303
    • 12.15 Security Review 304
    • 12.16 A Safe Test Setup 306
    • 12.17 Client Configuration 307
    • 12.18 Hands-On Lab: Triage, Diagnose, and Trigger Safely 308
    • 12.19 Testing Strategy 309
    • 12.20 Extending the Server 311
    • 12.21 Common Mistakes 311
    • 12.22 The GitLab MCP Checklist 312
    • 12.23 Summary and What Comes Next 314
  • 13 Building a DevOps Infrastructure MCP Server 315
    • 13.1 The Wrong Way Is a Remote Shell 316
    • 13.2 Server Capability Overview 317
    • 13.3 Threat Model and Safety Boundary 318
    • 13.4 Project Structure 319
    • 13.5 Allowlist Configuration 320
    • 13.6 Command Dispatcher Design 322
    • 13.7 Safe Subprocess Execution in Python 324
    • 13.8 Output Sanitization 326
    • 13.9 Tool Surface Design 327
    • 13.10 Implementing the Tools 328
    • 13.11 Resources for DevOps Context 331
    • 13.12 Prompt Templates for Incident Workflows 332
    • 13.13 Audit Logging 334
    • 13.14 Dry-Run and State-Changing Operations 335
    • 13.15 Local Test Environment 336
    • 13.16 Client Configuration 336
    • 13.17 Hands-On Lab: Inspect Safely and Try to Break It 337
    • 13.18 Testing Strategy 339
    • 13.19 Extending the Server Safely 340
    • 13.20 Common Mistakes 341
    • 13.21 The DevOps MCP Checklist 341
    • 13.22 Summary and What Comes Next 343
  • 14 Building a Memory and Knowledge MCP Server 345
    • 14.1 Memory Turns Sessions into Continuity 346
    • 14.2 Server Capability Overview 346
    • 14.3 Memory Design Principles 347
    • 14.4 SQLite as the Default Backend 348
    • 14.5 Project Structure 349
    • 14.6 The SQLite Schema 350
    • 14.7 The Database Access Layer 351
    • 14.8 Tool Surface Design 353
    • 14.9 Implementing the Tools 354
    • 14.10 Memory Resources 357
    • 14.11 Prompt Templates for Memory Workflows 358
    • 14.12 Memory Hygiene 360
    • 14.13 Privacy and Sensitive Data 361
    • 14.14 Full-Text Search 363
    • 14.15 Semantic Search and pgvector (Preview) 364
    • 14.16 Error Handling 366
    • 14.17 Security Review 367
    • 14.18 Client Configuration 369
    • 14.19 Hands-On Lab: Build a Memory and Use It 369
    • 14.20 Testing Strategy 371
    • 14.21 Extending the Server 372
    • 14.22 Common Mistakes 373
    • 14.23 The Memory MCP Checklist 373
    • 14.24 Summary and What Comes Next 375
  • 15 Testing, Debugging, and the MCP Inspector 379
    • 15.1 If You Cannot Test It, You Cannot Ship It 380
    • 15.2 The MCP Testing Pyramid 380
    • 15.3 Debugging by Lifecycle Phase 381
    • 15.4 The MCP Inspector 383
    • 15.5 Connecting a Stdio Server to the Inspector 384
    • 15.6 Debugging Failed Startup 385
    • 15.7 Debugging Handshake Failures 386
    • 15.8 Debugging Tool Failures 387
    • 15.9 Debugging Resources and Prompts 388
    • 15.10 Python Testing Strategy 389
    • 15.11 TypeScript Testing Strategy 392
    • 15.12 Protocol-Level Tests 394
    • 15.13 Stdio Integration Tests 396
    • 15.14 Security Test Cases 398
    • 15.15 Testing the Four Reference Servers 399
    • 15.16 CI Integration 400
    • 15.17 Test Data and Fixtures 401
    • 15.18 The Manual Debugging Checklist 402
    • 15.19 Hands-On Lab: Probing the notes-server 403
    • 15.20 Summary and What Comes Next 404
  • 16 Packaging, Publishing, and SSE Deployment 405
    • 16.1 Local Server vs. Production Service 406
    • 16.2 The Deployment Decision Framework 406
    • 16.3 Packaging Goals 407
    • 16.4 Python Docker Packaging 408
    • 16.5 TypeScript Docker Packaging 410
    • 16.6 Docker Compose for Local Deployment 411
    • 16.7 From Stdio to SSE 412
    • 16.8 SSE Server Structure in TypeScript 413
    • 16.9 SSE Server Structure in Python 414
    • 16.10 Authentication and Authorization for SSE 415
    • 16.11 Reverse Proxy Deployment 416
    • 16.12 Scaling an SSE Deployment 418
    • 16.13 Rate Limiting at the Network Edge 419
    • 16.14 Health Checks and Readiness 419
    • 16.15 Logging and Observability 421
    • 16.16 Environment Variables and Secrets 422
    • 16.17 Versioning Server Capabilities 423
    • 16.18 Publishing Server Artifacts 425
    • 16.19 Upgrade and Maintenance Strategy 426
    • 16.20 Deployment for the Four Reference Servers 427
    • 16.21 Hands-On Lab: Containerize and Deploy the GitLab Server 428
    • 16.22 Common Mistakes 430
    • 16.23 The Production Deployment Checklist 431
    • 16.24 Summary, and the End of the Road 432

Get the free sample chapters

Click the buttons to get the free sample in PDF or EPUB, or read the sample online here

The Leanpub 60 Day 100% Happiness Guarantee

Within 60 days of purchase you can get a 100% refund on any Leanpub purchase, in two clicks.

See full terms...

Earn $8 on a $10 Purchase, and $16 on a $20 Purchase

We pay 80% royalties on purchases of $7.99 or more, and 80% royalties minus a 50 cent flat fee on purchases between $0.99 and $7.98. You earn $8 on a $10 sale, and $16 on a $20 sale. So, if we sell 5000 non-refunded copies of your book for $20, you'll earn $80,000.

(Yes, some authors have already earned much more than that on Leanpub.)

In fact, authors have earned over $15 million writing, publishing and selling on Leanpub.

Learn more about writing on Leanpub

Free Updates. DRM Free.

If you buy a Leanpub book, you get free updates for as long as the author updates the book! Many authors use Leanpub to publish their books in-progress, while they are writing them. All readers get free updates, regardless of when they bought the book or how much they paid (including free).

Most Leanpub books are available in PDF (for computers) and EPUB (for phones, tablets and Kindle). The formats that a book includes are shown at the top right corner of this page.

Finally, Leanpub books don't have any DRM copy-protection nonsense, so you can easily read them on any supported device.

Learn more about Leanpub's ebook formats and where to read them

Write and Publish on Leanpub

You can use Leanpub to easily write, publish and sell in-progress and completed ebooks and online courses!

Leanpub is a powerful platform for serious authors, combining a simple, elegant writing and publishing workflow with a store focused on selling in-progress ebooks.

Leanpub is a magical typewriter for authors: just write in plain text, and to publish your ebook, just click a button. (Or, if you are producing your ebook your own way, you can even upload your own PDF and/or EPUB files and then publish with one click!) It really is that easy.

Learn more about writing on Leanpub