Building My First MCP: Mistakes and All
Built an MCP to manage Coolify from my editor. The OpenAPI spec was too big for Claude to handle, so I learned to work in chunks.
Building My First MCP: Mistakes and All
I wanted to manage my Coolify server from inside Cursor. Run deploys, check logs, update env vars, all without leaving my editor. The Model Context Protocol (MCP) seemed perfect for this.
Claude knows about MCPs. It can write MCP code. But "can write" and "writes good MCPs" are different things. I learned this the hard way.
The OpenAPI Problem
Coolify has an extensive API. Like, 70+ endpoints. I figured I'd give Claude the OpenAPI spec and let it generate all the tools.
The spec is nearly 6000 lines.
Claude choked on it. Not literally, but the outputs were garbage. It would forget endpoints it had just read about. Mix up parameter types. Generate tools that called non-existent methods.
Too much context. The model was drowning.
The Solution: Work in Chunks
I ended up creating Cursor rules that forced a specific workflow:
# Coolify MCP Development Workflow
## Requirements
1. Start by reviewing feature documentation in docs/features
2. Verify endpoint exists in openapi.yaml specification
3. Follow existing implementation patterns
4. Keep tests focused and properly mocked
One feature at a time. One endpoint at a time. Check the spec, write the type, write the client method, write the tool, write the test. Commit. Move on.
This was slower but actually worked. Each chunk fit in context. Claude could see the pattern from existing code and follow it.
Enforcing Git Discipline
Claude loves to vibe code its way into a mess. It'll make changes across 10 files, break something, then try to fix it by making more changes. Before you know it, you've got a diff with 500 lines and no idea what still works.
I added a rule that forces feature branching:
# Feature Development Workflow
## Requirements
- Start from up-to-date main branch
- Create feature branch (feature/feature-name)
- Commit frequently to trigger pre-commit hooks
- Push completed work to remote for PR review
## Critical Points
- NEVER skip tests for new functionality
- Commit OFTEN to utilize pre-commit hooks
The pre-commit hooks run linting, formatting, and tests on every commit. When Claude commits broken code, the hooks fail, and the error context goes back into the conversation. Claude sees what's wrong and fixes it.
This saved me so many times. Claude would generate something with a type error, commit it, hook fails, error message appears, Claude fixes it. All without me having to copy and paste anything.
The Chonky Spec Problem (Solved)
I mentioned the OpenAPI spec was too big. While writing this post, I ran it through Claude to check for typos, and it said "other developers probably have this problem too."
Good point.
So I asked it for a solution (chunk the spec into smaller bits), then asked for a Lovable.dev prompt to build a tool for it.
Single shot: https://chunkify-openapi.lovable.app/
That's the future right there. Problem → Solution idea → Prompt → Built. Whole thing took maybe 15 minutes.
What the MCP Actually Does
After all that, the Coolify MCP gives Claude access to:
- Server management (list, check status, validate connections)
- Application deployment (start, stop, restart, deploy)
- Environment variables (create, update, delete)
- Logs (pull application logs for debugging)
- Project management (create, update, organize)
Instead of copying UUIDs from the Coolify dashboard and pasting them into commands, I just say "restart the progress app" and Claude figures out which UUID that is.
Using It
For Claude Desktop:
"coolify": {
"command": "npx",
"args": ["-y", "@masonator/coolify-mcp"],
"env": {
"COOLIFY_ACCESS_TOKEN": "your-token",
"COOLIFY_BASE_URL": "https://cool.yourdomain.com"
}
}
For Claude Code, it's even simpler - just add it to your MCP config.
The repo with all the rules and docs: https://github.com/StuMason/coolify-mcp
Key Lessons
- Don't feed the model more than it can handle - Break big specs into small chunks
- Use rules to enforce workflow - Claude follows instructions well when they're explicit
- Pre-commit hooks are your friend - Let them catch Claude's mistakes automatically
- Commit often - Small commits = smaller blast radius when things break
- One feature at a time - Resist the urge to implement everything at once
Get the Friday email
What I shipped this week, what I learned, one useful thing.
No spam. Unsubscribe anytime. Privacy policy.