Module 5 — Building MCP Servers

Building Your Own MCP Server
(No, Seriously)

Until now you've been a consumer of MCP servers. This module flips the table. You're now the person building the server that someone else's agent calls. That's a very different kind of power — and it comes with some responsibility.

What You'll Learn
1

The two paths to building an MCP server in Postman — visual (Flows) vs. API-first (Generator)

2

The anatomy of a toolDefinition scenario and how to write one that actually makes sense

3

How the MCP Generator translates your existing API requests into agent-ready tools

4

Which path is right for your use case — answered by a decision tree, not a coin flip

 
Path A The Visual Builder — Postman Flows

Postman Flows lets you build an MCP server without touching a line of server code. The mechanism is a special kind of deployed Flow called an Action — a flow that lives in the cloud and responds to HTTP requests. When you give that action a toolDefinition scenario, it becomes an MCP server. Clients can connect to it, see its tools, and call them.

🏧
Mental model
Think of it as a vending machine you deploy to the cloud. You stock it with tools (the toolDefinition scenario). Anyone with the URL can ask what's in it (Load Capabilities) and request an item (Run). The machine handles the rest. You wrote zero server code.

Anatomy of a toolDefinition

A toolDefinition is just a JSON scenario in your Flow. It has one required section and two optional ones. Click each section below to expand it — the greeter example runs through all three.

Each tool has a name (what the agent calls), a description (what the agent reads to decide whether to use it — write this thoughtfully), and an inputSchema (the arguments it accepts).

{ "tools": [ { "name": "greeter", "description": "Says hello to a person by their first name", "inputSchema": { "type": "object", "properties": { "first_name": { "type": "string", "description": "The person's first name" } }, "required": ["first_name"] } } ] }
⚠️ description is load-bearing. The agent reads this to decide whether to call your tool. Vague descriptions get skipped. "Gets the user's current Slack status message" beats "gets user status" every time.

Each property in inputSchema.properties becomes an argument when the tool is called. In Postman Flows, you access it at arguments.first_name.

Prompts let your server suggest structured conversation starters to the client. Think of them as pre-written instructions that a client can surface to a user or pass to an LLM.

"prompts": [ { "name": "request-code-review", "title": "Request Code Review", "description": "Ask the LLM to review a file for anomalies", "arguments": [ { "name": "file", "description": "The data file to review", "required": true } ] } ]
Prompts are identified by name (not URI). When a client calls a prompt, the action receives a JSON object with name and arguments — the outer MCP envelope is stripped away for you.

Resources provide static context to a model — files, documents, data — identified by URI (not name). Resource templates parameterize that URI using RFC 6570 URI Templates.

"resources": [ { "uri": "http://example.com/data.json", "name": "data.js", "mimeType": "application/json" } ], "resourceTemplates": [ { "uriTemplate": "file:///{path}", "name": "Project Files", "mimeType": "application/octet-stream" } ]
Resource actions receive a { uri } object. Resource template actions receive the resolved URI with any template variables filled in. The outer MCP envelope is stripped — same as prompts.
See it in context
// toolDefinition scenario body — single tool { "tools": [ { "name": "greeter", "description": "Says hello to a person by their first name", "inputSchema": { "type": "object", "properties": { "first_name": { "type": "string", "description": "The person's first name" } }, "required": ["first_name"] } } ] } // In your Flow canvas, a Template block reads: // "Hello, " + {{steps.select.output}} // where the Select block path is: arguments.first_name
// toolDefinition scenario body — two tools { "tools": [ { "name": "get_weather", "description": "Returns current weather for a given city", "inputSchema": { "type": "object", "properties": { "city": { "type": "string", "description": "City name" } }, "required": ["city"] } }, { "name": "get_forecast", "description": "Returns 5-day forecast for a given city", "inputSchema": { "type": "object", "properties": { "city": { "type": "string", "description": "City name" }, "units": { "type": "string", "description": "metric or imperial" } }, "required": ["city"] } } ] } // In your Flow canvas, use a Condition block first: // if body.name == "get_weather" → weather branch // if body.name == "get_forecast" → forecast branch // Each branch uses a Select block to parse arguments.city
 
Path B The API Network Generator

You have an API. Maybe several. The MCP Generator reads your existing Postman requests and generates a working MCP server, with one tool per request, handling auth, base URLs, and parameters automatically.

🌐
Mental model
Think of the Generator as a translator who reads your instruction manual (the API) and rewrites it as a list of commands your agent can natively understand. Each request becomes a tool. The auth, the base URL, the parameters — all carried over. You didn't write any MCP JSON. The translator did.

The 8-Step Generation Flow

Walk through the full generation process below. Each step has a "why this matters" annotation so you know what's actually happening under the hood.

 

Which Path Is Right for You?

Answer three questions and get a concrete recommendation. No waffling, no "it depends" — just your path.

Interactive decision tree
 

See Both Paths Side by Side

The demo below builds the same simple MCP server two ways — Flows on the left, Generator on the right. Same result, different journeys. Watching them back to back is the fastest way to decide which workflow fits your brain.

 
Video Demo — Flows vs. Generator: Side-by-Side Build
Replace this block with the embedded comparison video when ready
 
🚀 Try This — Pick Your Path
Flows path
Use the greeter example as a template, deploy it, connect to it with an MCP request, and then modify the tool to do something you'd actually use — a formatter, a lookup, a calculation. One tool is enough.
Generator path
Find 3 requests in any public workspace that relate to a tool you use daily. Generate the server, unzip it, and run npm run list-tools. Read what got created. Does it match what you'd have written?
🌐
Up Next

Connecting to the Outside World