AI & LLM APIs cookbook · Intermediate

Expose an internal API as an MCP server

Make an internal system (tickets, inventory) available to every MCP-capable AI app once, instead of per app.

Create a free account to save this page, take notes and track your progress. Sign in

Approach

Use the MCP Python SDK's MCPServer. Type-hinted functions become tools with JSON schemas; docstrings become descriptions. Design task-shaped tools with small outputs and pagination, and annotate read-only and destructive tools.

Solution

from mcp.server import MCPServer
from mcp.types import ToolAnnotations

mcp = MCPServer("Inventory")


@mcp.tool(annotations=ToolAnnotations(read_only_hint=True))
def find_products(query: str, in_stock_only: bool = True, limit: int = 20, cursor: int = 0) -> dict:
    '''Search products by name or SKU. Returns sku, name, stock and price, 20 per page.'''
    rows = inventory.search(query, in_stock_only=in_stock_only)        # your data access
    page = rows[cursor:cursor + min(limit, 50)]
    return {"products": [{"sku": r.sku, "name": r.name, "stock": r.stock, "price": r.price} for r in page],
            "next_cursor": cursor + len(page) if cursor + len(page) < len(rows) else None}


@mcp.tool(annotations=ToolAnnotations(destructive_hint=True))
def adjust_stock(sku: str, delta: int, reason: str) -> dict:
    '''Change stock for a SKU by delta (negative to remove). Requires a reason; confirm with a human first.'''
    if abs(delta) > 500:
        raise ValueError("Adjustments over 500 units need a manual stock count.")
    return inventory.adjust(sku, delta, reason)


if __name__ == "__main__":
    mcp.run()                                       # stdio; mcp.run(transport="streamable-http") for remote

Pitfalls

  • Mirroring REST endpoints one-to-one (list_all_products), flooding the agent's context.
  • Giving the server broad credentials; use a service account with only what the tools need.
  • Renaming or removing tools without warning; agents and prompts depend on them.

Variations

  • Serve remotely with mcp.streamable_http_app(stateless_http=True) behind your load balancer.
  • Expose reference data (price lists, docs) as resources with @mcp.resource(...).

Further reading: MCP Python SDK

Reference: https://github.com/modelcontextprotocol/python-sdk

More AI & LLM APIs recipes

Was this page helpful?