TsgcWSAPIServer_MCP component.
TsgcWSAPIServer_MCP exposes the Model Context Protocol (MCP) over an sgcWebSockets HTTP server endpoint. The component bridges incoming HTTP requests with the TsgcAI_MCP_Server engine so that MCP-compatible clients can negotiate sessions, enumerate prompts/resources/tools, and invoke tools through JSON-RPC style calls.
When the component is attached to an HTTP server, the following endpoints and behaviors are served automatically alongside /mcp, without any new property to enable them. This enables out-of-the-box compatibility with web-based MCP connectors such as claude.ai, which require OAuth 2.1 with Dynamic Client Registration over CORS.
OPTIONS preflight to any handled path returns 204 No Content with the following headers:
Access-Control-Allow-Origin: echo of the request Origin header, or * if missing.Access-Control-Allow-Methods: POST, GET, DELETE, OPTIONSAccess-Control-Allow-Headers: content-type, mcp-session-id, mcp-protocol-version, authorization, acceptAccess-Control-Expose-Headers: mcp-session-idAccess-Control-Max-Age: 86400Strict-Transport-Security: max-age=31536000Access-Control-Allow-Origin, Access-Control-Expose-Headers and Strict-Transport-Security.
WWW-Authenticate. When MCPOptions.AuthenticationOptions.ApiKey (or CustomHeader) is enabled and the request has no or wrong credentials, the server responds with 401 and a header of the form:
Bearer realm="MCP", resource_metadata="https://<host>/.well-known/oauth-protected-resource"
/mcp, supporting PKCE (S256), authorization-code and refresh-token grants, and Dynamic Client Registration:
| Path | Spec | Behavior |
|---|---|---|
GET /.well-known/oauth-authorization-server |
RFC 8414 | JSON authorization server metadata. Advertises PKCE (S256), authorization_code + refresh_token grants, public-client + client_secret_basic auth methods, dynamic registration at /oauth/register, and the mcp scope. |
GET /.well-known/oauth-protected-resource |
RFC 9728 | JSON describing the MCP endpoint as a protected resource and pointing at this server as the authorization server. |
POST /oauth/register |
RFC 7591 (DCR) | Accepts a JSON client registration body (client_name, redirect_uris). Issues a generated client_id (no client_secret — public client). Returns 201 with the registered client information response. |
GET /oauth/authorize |
RFC 6749 + RFC 7636 | Renders an HTML consent page. Required query params: client_id, redirect_uri, response_type=code, code_challenge, code_challenge_method=S256, state, scope. |
POST /oauth/authorize |
RFC 6749 | Processes the consent form. The user must enter the same value as MCPOptions.AuthenticationOptions.ApiKey.Value to approve. On approve, redirects to redirect_uri with ?code=...&state=.... On deny or wrong key, redirects with ?error=access_denied&state=... or re-renders the form. |
POST /oauth/token |
RFC 6749 + RFC 7636 | Form-encoded body. Supports grant_type=authorization_code (validates PKCE: BASE64URL(SHA256(code_verifier)) == code_challenge) and grant_type=refresh_token. Issues a 1-hour bearer access token plus a refresh token. Auth codes expire after 60 seconds and are single-use. |
MCPOptions.AuthenticationOptions.ApiKey.Enabled is True, the Authorization: Bearer <X> header on /mcp requests is accepted if <X> matches either the configured static ApiKey.Value, or a currently-valid OAuth-issued access token (issued via the flow above).
OnMCPHTTPRequest. Handlers wired to OnMCPHTTPRequest can short-circuit any of the above behaviors by setting Handled := True.
Besides the HTTP transports, the MCP server engine can also run over the stdio transport. The TsgcAI_MCP_Server_Stdio host wraps the same TsgcAI_MCP_Server engine, reads newline-delimited JSON-RPC messages from standard input and writes responses to standard output (UTF-8). This is the transport used by local AI agents such as Claude Code, which spawn the server as a child process. No HTTP server, port or TLS configuration is required.
Register tools, prompts and resources on TsgcAI_MCP_Server_Stdio.MCPServer exactly as on the HTTP component, then call Run to start processing messages. Standard output is the protocol channel, so send any logging to standard error instead.
var
oServer: TsgcAI_MCP_Server_Stdio;
oTool: TsgcAI_MCP_Tool;
begin
oServer := TsgcAI_MCP_Server_Stdio.Create(nil);
try
oServer.ServerInfo.Name := 'MyDelphiServer';
oServer.ServerInfo.Version := '1.0';
oTool := oServer.MCPServer.Tools.AddTool('add', 'Adds two numbers');
oTool.InputSchema.Properties.AddProperty('a', True, aimcpjtNumber);
oTool.InputSchema.Properties.AddProperty('b', True, aimcpjtNumber);
oServer.MCPServer.OnMCPRequestTool := OnRequestTool;
oServer.Run; // reads stdin, writes stdout, blocks until EOF
finally
oServer.Free;
end;
end;