Documentation Blog Free tools [email protected]Log in

How to create an MCP server: from a function to a tool your agent can call

Building an MCP server: wrap a function as a tool with a schema, serve over stdio or HTTP, an agent discovers and calls itYour MCP server@tool def get_price( sku: str) -> dictname · description · schematransport: stdio | HTTPinitialize · tools/listtools/call →← resultClientClaude · CursorVS Code · Clinediscovers your toolsBackendAPI · DB · web

Creating an MCP server means writing a small program that exposes functions as tools an AI client can discover and call — you define each tool with a name, a description and a typed input schema, serve it over a transport, and any MCP-capable host (Claude, Cursor, VS Code, Cline) can use it. The official SDKs do the protocol work; your job is the tools and their descriptions.

Before you write code: what should it expose?

An MCP server is worth building when you have a capability a model should be able to invoke on its own — query your database, hit your internal API, act on your product, or fetch live data. Start by listing the two or three actions that matter, not everything possible. A focused server with four well-described tools beats a sprawling one with forty the model can't choose between. If you are wrapping an existing API, the tools usually map to its most useful endpoints, reshaped for how a model thinks about the task rather than how the API is organized.

Step 1: pick the SDK and transport

Official SDKs exist for TypeScript and Python and handle the JSON-RPC protocol, the handshake and message routing for you. Choose the language your backend already lives in. Then pick a transport: stdio if the server runs locally and the client launches it as a subprocess (the common case for developer tools), or streamable HTTP if it runs remotely and clients connect over the network. Start with stdio — it is the simplest to develop and test.

Step 2: define a tool

A tool is a function plus metadata. In the Python SDK it is close to a decorated function:

from mcp.server.fastmcp import FastMCP

mcp = FastMCP("price-tools")

@mcp.tool()
def get_price(sku: str) -> dict:
    """Get the current price and stock for a product SKU.
    Call this when the user asks about a specific product's price
    or availability."""
    row = db.lookup(sku)              # your real logic
    return {"price": row.price, "in_stock": row.stock > 0}

if __name__ == "__main__":
    mcp.run()                         # stdio by default

Three things carry the weight: the type hints become the input schema the client validates against, the docstring becomes the description the model reads to decide whether to call the tool, and the return value is what lands back in the model's context. Get the docstring right and the model calls the tool correctly; leave it vague and the tool sits unused.

Step 3: run and connect it to a client

Register the server in your client's config. For Claude Desktop or Claude Code that is a small JSON entry naming the command that launches it:

{
  "mcpServers": {
    "price-tools": {
      "command": "python",
      "args": ["/path/to/server.py"]
    }
  }
}

Restart the client, and your tools appear. Cursor, VS Code and Cline use the same shape with their own config location. The client handles the initialize handshake and tools/list automatically — you just see the tool become available to the model. We break down that request flow in how MCP servers work.

The rules that decide whether your tools get used

  • Write descriptions for the model, not the docs. State when to call the tool, not just what it does — "Call this when the user asks about current prices" outperforms "Returns price data." This single habit moves the needle most.
  • Keep inputs flat and typed. Simple, well-named parameters with clear types are chosen correctly far more often than nested config objects.
  • Return structured, compact results. Give the model what it needs, not your API's full envelope. Trim noise before it hits the context window.
  • Handle errors as data. Return a clear error message rather than throwing — the model can read it and retry or adjust.
  • Scope credentials tightly. The server runs with real permissions and is called by a model reading untrusted content; give it only the access its tools need, and gate irreversible actions.

Wrapping an existing API vs building capability

Most first MCP servers wrap something that already exists — an internal API, a SaaS, a database. That is the fast, high-value path: the capability is proven, you are just adding the discoverable, model-friendly interface on top. Building genuinely new capability (a browser that navigates, a data collector that fetches the live web) is a bigger job, which is why many teams connect an existing web-data server instead of writing one. Our MCP server is exactly that shape — a thin protocol adapter over a web-data API, giving an agent search, scrape, crawl and map as tools without you building the fetch, proxy and parsing stack. If your server needs to reach the open web, wrapping a capability like that is faster than reinventing it; if it needs your proprietary data, you build it, and the pattern above is the whole recipe. The docs show the client setup for each host.

Sources & further reading

FAQ

Quick answers on how to create mcp server.

Something else? Ask us →

What language should I write an MCP server in?

Use the language your backend already lives in — official SDKs cover TypeScript and Python and handle the protocol for you. If you're wrapping an existing service, match its stack so you can reuse its client libraries and auth. The protocol is language-agnostic, so there's no performance reason to switch.

What is the difference between stdio and HTTP transport?

With stdio the client launches your server as a local subprocess and they exchange messages over stdin/stdout — simplest for developer tools running on the same machine. Streamable HTTP is for remote servers clients connect to over the network. Start with stdio for local development; move to HTTP when the server needs to be hosted.

How does a model know which tool to call?

It reads each tool's name, description and input schema, which your server advertises during the handshake. The description is decisive — a model calls a tool that clearly states when it applies and ignores or misuses a vague one. Write descriptions that name the trigger condition, not just the function.

Can I turn an existing API into an MCP server?

Yes, and it's the most common first project. Map your API's most useful endpoints to tools, reshape the parameters for how a model thinks about the task rather than how the API is organized, and add descriptions naming when to call each. Wrapping a proven API is far faster than building new capability.

Do I need to build a web-scraping MCP server myself?

Only if you want to own the fetch, proxy and parsing stack. If your agent just needs live web data, connecting an existing web-data MCP server gives it search, scrape, crawl and map as tools immediately — reserve custom server-building for your proprietary capabilities where no server exists.

Need the web as tools without building the stack?

Connect our MCP server and your agent gets search, scrape, crawl, map, batch and seo_audit — residential proxies underneath, pay per success. Free open package, $2 of usage every month.

Related reading