Case Study

MCP Image Placeholder

2 providers Deterministic URLs Stateless tools

When I looked at how AI tools were building image placeholders, the pattern was pretty familiar: a lot of string concatenation and half‑remembered URL formats for services like placehold.co and picsum.photos. Each integration had its own way of doing it, and it was easy to make small mistakes.

I didn’t need a full image service. I just wanted a small, predictable way to ask for a placeholder image URL without thinking about provider quirks.

MCP Image Placeholder is that small piece: an MCP server that exposes a single tool, image_placeholder, over JSON‑RPC. You give it a provider and some parameters, and it returns a URL string.


Why Build It as an MCP Server

In the MCP world, tools run alongside editors and AI agents, speaking over standard input and output. Many clients can already talk to MCP servers, so adding a new tool there is often simpler than deploying another HTTP API.

For this project, that meant:

  • wrapping the MCP SDK’s server,
  • registering a single image_placeholder tool with a clear input schema, and
  • returning a plain text URL on success.

There’s no UI and no separate web server. The process focuses on answering one kind of request and exiting cleanly when asked to stop.


Basic Configuration and Validation

To keep the behavior consistent, I put configuration and validation in simple, separate layers.

Configuration reads environment variables once, applies defaults, and checks for obvious issues (like invalid log levels or dimension ranges). After that, the rest of the code only deals with a structured config object; it never talks to process.env directly.

Validation sits between the incoming request and the URL builders. It checks:

  • that the provider is supported,
  • that width and height fall within configured bounds, and
  • that provider‑specific options are not mixed up (for example, picsum options being passed to placehold).

Anything that doesn’t pass these checks is rejected with a clear error before a URL is constructed.


Provider-Specific URL Builders

Each provider has its own URL rules: different base URLs, query parameters, and options for things like colors or blur. Rather than bake all of that into one function, I use a small factory that returns a provider‑specific builder.

The pattern is:

  • validation makes sure the overall request is reasonable,
  • the factory chooses the right builder, and
  • the builder turns the provider’s options into a URL string.

That separation keeps the common logic simple and makes it easier to add or adjust providers later without surprising other parts of the system.


Errors and Logging at a Practical Level

Because this runs inside AI tools, it’s important that errors are straightforward to interpret.

The server uses a small set of error types to describe configuration issues, validation failures, provider problems, and unexpected server errors. Logs are written in a simple structured format so they can be inspected during development or forwarded somewhere in more complex setups.

The main intent is not to be fancy, but to make it easy to see what went wrong when something does.


Tests Instead of Documentation Pages

There’s no long provider guide for this project. Instead, tests cover the main behaviors:

  • basic URLs for each provider,
  • how dimensions are handled,
  • common combinations of options, and
  • failure cases when inputs are out of range or mismatched.

There are also a few tests around configuration and error handling. Together, they act as a living description of what the tool expects and returns.


What I Left Out and Why

MCP Image Placeholder does not fetch images, cache anything, or manage user state. It only builds URLs. That was intentional.

By keeping the scope small, the server stays easy to understand and cheap to run. Other parts of a system—browsers, HTTP clients, or downstream services—are free to fetch and cache images however they want.

From my side, the main goal was to give AI tools a straightforward way to say, “I need a placeholder image with these dimensions and style,” and get back a usable URL without worrying about the specifics of each provider. On that front, a single MCP tool is enough.