Building Your Own MCP Server for AI

Build a Useful MCP Server

Turn several REST endpoints into a small, named MCP interface instead of a 1:1 API copy.

A useful server is opinionated. Three tools that match how people talk beat thirty tools that match how the backend was generated.

Start from jobs, not paths

Write the sentences a teammate would type: “What’s open on my board?” “File a bug with this title.” “Show the last failed deploy.” Those sentences become tools. The URLs stay inside the functions.

A thin board, not every Jira field

from typing import Any

import httpx
from mcp.server.mcpserver import MCPServer

mcp = MCPServer("tiny-board")
API = "https://httpbin.org"  # stand-in; swap for your tracker


@mcp.tool()
def list_open_issues(limit: int = 5) -> dict[str, Any]:
    '''List a few open issues. Keep limit small so the model is not flooded.'''
    limit = max(1, min(limit, 10))
    # Real code: GET /issues?state=open&per_page=limit
    return {"ok": True, "issues": [{"id": 1, "title": "Example", "state": "open"}][:limit]}


@mcp.tool()
def file_bug(title: str, body: str) -> dict[str, Any]:
    '''Create one bug. Title is required; body can be short.'''
    title = title.strip()
    if len(title) < 8:
        return {"ok": False, "error": "title must be at least 8 characters"}
    # Real code: POST /issues with {title, body, labels: ["bug"]}
    return {"ok": True, "id": 99, "title": title}

You skipped search syntax, custom fields, and delete. That is design, not laziness. Designing MCP for AI is the longer argument.

Shared HTTP client

Create one httpx.Client (or a helper) with base URL, token, and timeout. Do not open a new client with a slightly different User-Agent in every tool.

Check it

  1. List tools in the host. You should see two names a human would pick, not get_issues and post_issues.
  2. Call file_bug with a two-word title and confirm the validation error.
  3. Write a third tool only if you have a third job. Resist “and also list closed.”

Next: run the same ideas over the network.