mctxdocs
Build Your MCP Server

Core Concepts

The mental model behind @mctx-ai/mcp — server, handlers, primitives, input schemas, and what the framework handles so you don't have to.

Need help? Connect help.mctx.ai for instant answers.

What you write

A createServer() call that chains .tool(), .resource(), and .prompt() registrations, then exports a fetch handler.

import { createServer, T } from "@mctx-ai/mcp";

const server = createServer({ instructions: "Helps users manage tasks." });

const addTask = ({ title }) => `Task "${title}" created.`;
addTask.description = "Create a new task";
addTask.input = { title: T.string({ required: true }) };

server.tool("add_task", addTask);

export default { fetch: server.fetch };

That is the complete shape of an MCP server. Everything else — protocol, auth, transport — is handled for you.

The handler signature

Every handler follows the same pattern:

(args, ask?, ctx?) => result | Promise<result>
  • args — the validated input your handler declared, delivered as a plain object.
  • ask — a function to request an LLM completion from the connected client; null when the client doesn't support sampling. Always check before calling. See Sampling.
  • ctx — platform context injected by mctx. Use ctx.userId to identify the authenticated subscriber. See User Identity.

None of these parameters require any setup. The framework passes them automatically on every request.

Three primitives

Tools — actions clients invoke. Your function runs, returns a result, and the client receives it. Use tools for anything that does work: querying a database, calling an API, computing a value. See Tools.

Resources — data clients read. Identified by a URI (exact or templated), a resource handler returns content that the client can embed in context. Use resources to expose documents, schemas, or per-user data. See Resources.

Prompts — reusable message templates. A prompt handler returns a string or a structured conversation that pre-fills the LLM's message history. Use prompts to package repeatable task setups. See Prompts.

Input schema with T

The T type system lets you describe tool and prompt inputs. Schemas are compile-checked and used by the framework to validate input before your handler runs.

import { T } from "@mctx-ai/mcp";

handler.input = {
  query: T.string({ required: true, description: "Search query" }),
  limit: T.number({ min: 1, max: 100, default: 10 }),
  approved: T.boolean({ default: false }),
};

Available builders: T.string, T.number, T.boolean, T.array, T.object. Each accepts options for constraints, defaults, and descriptions. Bad input is rejected before your code runs — you never receive malformed data.

Running it

Pass the server's fetch to a runtime. During development, @mctx-ai/dev wraps it with hot reload and request logging:

npx mctx-dev index.js

For deployment, export fetch and mctx handles the rest. The same export format works as a Cloudflare Worker directly if you need to self-host.

What you don't have to do

The framework handles these automatically — you write none of this:

  • OAuth wiring — subscriber authentication and token validation are platform responsibilities.
  • JWT validation — mctx verifies every request before it reaches your handler.
  • Protocol transport — JSON-RPC parsing, MCP capability negotiation, SSE keepalives.
  • Client-mode handshake — capability advertisement based on what you registered happens automatically.
  • Input validation errors — malformed or missing required fields are rejected with safe error responses before your handler is called.

See something wrong? Report it or suggest an improvement — your feedback helps make these docs better.