Most MCP tutorials assume you're starting from scratch. In reality, you usually have a working tool or library and just want to expose it as a callable tool to an LLM agent. Here's the path I take that gets it done in 30 minutes of real work.
Step 1: Pick one tool, not five
Don't expose your whole API surface. Pick the one function a coding agent would actually call. For a docs site, that's search_docs. For a database, that's run_query. For an internal service, that's lookup_user. One tool, clear input schema, real value.
Step 2: Write the tool description like a docstring
The model will only call the tool well if the description is sharp. I write three sentences:
- What it does (verb + noun)
- When to use it (the user signal that should trigger it)
- What it returns (shape, not values)
Example:
search_docs(query, top_k=5): Search the company docs index. Use when the user asks a factual question about internal systems, processes, or past decisions. Returns a list of{title, url, snippet}sorted by relevance.
That's the whole tool spec. No ambiguity, no prose.
Step 3: Run Codex locally first
OpenAI Codex CLI is the fastest way to validate the tool works end-to-end:
codex --approval-mode suggest
Drop into a sandboxed directory, ask Codex to use the tool. If it picks the tool, calls it correctly, and uses the result in its answer, you're done. If it doesn't, the description is bad — go back to step 2.
Step 4: Wire it as an MCP server
Now wrap the tool in a real MCP server. The minimum is a FastMCP instance with one @mcp.tool():
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("internal-docs")
@mcp.tool(description="Search the company docs index...")
def search_docs(query: str, top_k: int = 5) -> list[dict]:
return docs_index.search(query, top_k=top_k)
if __name__ == "__main__":
mcp.run(transport="stdio")
Add it to your client's MCP config (Claude Desktop, Cursor, etc.). Restart, ask the same question. If it works in both Codex CLI and the host client, you have a real MCP server.
Step 5: Evals, not vibes
The last 10 minutes is an eval. Three questions your tool should answer correctly, three it should refuse to answer. If you can't list them, your tool isn't done — it's just running.
A small diagram
Here's the loop I end up with. Tools, model, results, repeat.
The boring truth is that the description is 80% of the work. Once that's right, the wiring is half an hour.

Top comments (0)