Server API
The registration and serving surface: TMCPServer from MCP.Server,
plus the two transports. The task-oriented walkthroughs live in the
guides; this page is the complete surface.
TMCPServer
constructor Create(const AName, AVersion: string);Name and version identify the server in serverInfo. Neither may be
empty. Configure and register on the fresh instance, then hand it to a
transport; configuration and registries freeze when the first session
is created, and later mutation raises EMCPServer.
Configuration properties
| Property | Type | Default | Meaning |
| --- | --- | --- | --- |
| Instructions | string | '' | Usage guidance surfaced via server/discover / classic initialize |
| CacheTtlMs | Integer | 300000 | SEP-2549 ttlMs caching hint on discover/list/read results; must be ≥ 0 |
| CacheScope | string | 'private' | SEP-2549 cacheScope; 'private' or 'public' |
| RedactErrorDetails | Boolean | False | True replaces exception detail with a correlation reference, logging the full error to stderr |
| DualEra | Boolean | True | Answer the classic initialize handshake alongside stateless 2026-07-28 requests |
| Name, Version | string | — | Read-only, from Create |
Semantics and guidance: Configuration.
Registering tools
Fourteen overloads along two axes — the seven schema-declaration
shapes below, each in plain-function and of object method handler
form:
// Raw JSON schema string
function RegisterTool(const AName, ADescription, AInputSchemaJson: string;
AHandler: TMCPToolHandler): TMCPToolOptions;
// Pre-assembled definition object (name/description/inputSchema)
function RegisterTool(ADefinition: TJSONObject;
AHandler: TMCPToolHandler): TMCPToolOptions;
// Fluent schema builder; optional output schema
function RegisterTool(const AName, ADescription: string;
constref AInputSchema: TMCPSchema;
AHandler: TMCPToolHandler): TMCPToolOptions;
function RegisterTool(const AName, ADescription: string;
constref AInputSchema, AOutputSchema: TMCPSchema;
AHandler: TMCPToolHandler): TMCPToolOptions;
// Typed argument class; optional output schema or output class
function RegisterTool(const AName, ADescription: string;
AArgsClass: TMCPArgsClass;
AHandler: TMCPArgsHandler): TMCPToolOptions;
function RegisterTool(const AName, ADescription: string;
AArgsClass: TMCPArgsClass; constref AOutputSchema: TMCPSchema;
AHandler: TMCPArgsHandler): TMCPToolOptions;
function RegisterTool(const AName, ADescription: string;
AArgsClass, AOutputClass: TMCPArgsClass;
AHandler: TMCPArgsHandler): TMCPToolOptions;Handler signatures:
TMCPToolHandler = function(AArguments: TJSONObject;
const ACtx: TMCPRequestContext): TMCPToolResult;
TMCPArgsHandler = function(AArgs: TMCPArgs;
const ACtx: TMCPRequestContext): TMCPToolResult;
// ...Method variants: identical, of objectEvery overload returns TMCPToolOptions for fluent annotation:
function Title(const ATitle: string): TMCPToolOptions;
function ReadOnlyHint(AValue: Boolean = True): TMCPToolOptions;
function DestructiveHint(AValue: Boolean = True): TMCPToolOptions;
function IdempotentHint(AValue: Boolean = True): TMCPToolOptions;
function OpenWorldHint(AValue: Boolean = True): TMCPToolOptions;
function ApplicationValidated: TMCPToolOptions;ApplicationValidated publishes a raw schema unchanged and hands
argument validation to the handler — see
Schemas.
Registering resources
procedure RegisterTextResource(const AUri, AName, AMimeType, AText: string;
const ADescription: string = '');
procedure RegisterResource(const AUri, AName, AMimeType: string;
AReader: TMCPResourceReader; const ADescription: string = '');
procedure RegisterResource(const AUri, AName, AMimeType: string;
AMethod: TMCPResourceMethod; const ADescription: string = '');
procedure RegisterResourceTemplate(const AUriTemplate, AName,
AMimeType: string; AReader: TMCPTemplateReader;
const ADescription: string = '');
procedure RegisterResourceTemplate(const AUriTemplate, AName,
AMimeType: string; AMethod: TMCPTemplateMethod;
const ADescription: string = '');Reader signatures:
TMCPResourceReader = function(const AUri: string;
const ACtx: TMCPRequestContext): TJSONArray;
TMCPTemplateReader = function(const AUri: string; AVars: TJSONObject;
const ACtx: TMCPRequestContext): TJSONArray;Readers return contents built with MCPTextContents /
MCPBlobContents — see Results and content. Template
matching is RFC 6570 level 1; the standalone matcher is public:
function MatchUriTemplate(const ATemplate, AUri: string;
out AVars: TJSONObject): Boolean;Registering prompts
Eight overloads: with or without declared arguments, message-array or result handlers, each in function and method shape:
procedure RegisterPrompt(const AName, ADescription: string;
AHandler: TMCPPromptHandler);
procedure RegisterPrompt(const AName, ADescription: string;
constref AArguments: TMCPPromptArguments;
AHandler: TMCPPromptHandler);
// same two with TMCPPromptResultHandler — the MRTR-capable shape
// whose handler returns TMCPPromptResult
// ...and all four as of-object Method variantsHandler signatures:
TMCPPromptHandler = function(AArguments: TJSONObject;
const ACtx: TMCPRequestContext): TJSONArray;
TMCPPromptResultHandler = function(AArguments: TJSONObject;
const ACtx: TMCPRequestContext): TMCPPromptResult;Arguments are declared fluently, starting from the PromptArguments
factory function:
function PromptArguments: TMCPPromptArguments;
function Add(const AName: string; const ADescription: string = '';
ARequired: Boolean = True): TMCPPromptArguments;The request context
Every handler receives TMCPRequestContext (from MCP.Protocol):
| Member | Meaning |
| --- | --- |
| ProtocolVersion | Negotiated revision for this request |
| ClientName, ClientVersion | From clientInfo; '' when absent |
| ClientCapabilities | The per-request capability object |
| HasCapability(Name) | Capability probe (used for MRTR gating) |
| LogLevel | Client's requested log floor; '' = no log opt-in |
| HasProgressToken, ProgressToken | Progress opt-in state |
| InputResponses, RequestState | MRTR retry payload — see Client requests |
| IsCancelled | Cooperative cancellation probe |
Introspection and the sans-I/O seam
function ToolCount: Integer;
function ResourceCount: Integer;
function PromptCount: Integer;
function CreateSession: TMCPSession;
function HandleMessage(ASession: TMCPSession; const ALine: string;
out AResponse: string): Boolean;
function HandleMessage(ASession: TMCPSession; const ALine: string;
ASink: TMCPLineSink; ASinkData: Pointer;
out AResponse: string): Boolean;
function OversizedLineResponse(AMaxLineLength: Integer): string;CreateSession / HandleMessage are the line-in/line-out core the
transports wrap — only custom transport authors call these directly
(see Architecture).
Stdio transport
From MCP.Transport.Stdio:
procedure RunMCPStdioServer(AServer: TMCPServer;
AMaxLineLength: Integer = MCP_STDIO_DEFAULT_MAX_LINE); // 4 MiB
procedure RunMCPStdioLoop(var AInput, AOutput: Text; AServer: TMCPServer;
AMaxLineLength: Integer = MCP_STDIO_DEFAULT_MAX_LINE);
procedure MCPLogToStderr(const AMessage: string);RunMCPStdioServer serves stdin/stdout until EOF — the spec's
graceful shutdown. RunMCPStdioLoop is the same loop over arbitrary
Text files, for tests and custom stream transports reusing the
newline framing.
Streamable HTTP transport
From MCP.Transport.HTTP:
constructor Create(AServer: TMCPServer);
procedure Run; // blocks until Stop
procedure Stop; // callable from another thread
property Port: Word;
property Address: string; // default 127.0.0.1
property EndpointPath: string; // default '/mcp'
property MaxBodyBytes: Integer; // default 4 MiB
property AllowedOrigins: TStringList; // exact-match additionsDeployment posture — loopback default, Origin allowlist, no TLS/auth,
modern era only — is covered in
Shipping your server.
On Unix, cthreads must be first in the program's uses clause.
Errors
EMCPServer is raised for API misuse: registration after freeze,
malformed schemas, empty names, nil/foreign sessions. Wire-level
problems never raise — they become JSON-RPC error responses.