MARS v.1.7.0 released: more features and AI support
A year after 1.6, MARS-Curiosity 1.7 is out. It is the largest release in a long time: more than 225 commits, a brand new documentation site, several new demos and one headline feature that I am particularly excited about — native MCP server support, which lets AI agents such as Claude or ChatGPT discover and call your Delphi code.
If you don’t know MARS: it is an open source, lightweight REST library for Delphi. You write plain classes, decorate them with attributes, and MARS takes care of routing, parameter binding, serialization, authentication and so on. The library is available on GitHub, and documented on the new documentation site.
Build MCP servers in Delphi
The Model Context Protocol is quickly becoming the standard way to give AI agents access to tools and data. With 1.7, any MARS server can also be an MCP server. There is no protocol code to write: derive a resource from TMCPResource, mark your methods with [MCPTool], and MARS generates the tool list and the JSON Schema of every parameter from RTTI.
[Path('mcp'), MCPServerInfo('My MCP Server', '1.0.0', 'Instructions for the agent')]
TMyMCPResource = class(TMCPResource)
public
[MCPTool('add_numbers', 'Adds two numbers and returns a structured result')]
function AddNumbers(
[MCPParam('a', 'First operand')] const A: Double;
[MCPParam('b', 'Second operand')] const B: Double): TCalculationResult;
end;
That is a complete MCP tool. Point Claude, ChatGPT, Open WebUI or the MCP Inspector to http://yourserver/rest/default/mcp and the agent can call it. Beyond the basics, you get:
- Tools, resources and prompts —
[MCPTool],[MCPResource](including URI templates) and[MCPPrompt], over the Streamable HTTP transport. - Database-backed tools —
TMCPDataResourcelets a tool simply return a FireDAC dataset; MARS serializes it for the agent. - Per-tool authorization — the same
[RolesAllowed]attribute you already use on REST methods. Tools a user is not entitled to are hidden from the tool list altogether, so different users see different tool sets on the same endpoint. - A built-in OAuth 2.1 authorization server — discovery, dynamic client registration, PKCE, refresh token rotation, optional persistence and a customizable login page. This is what makes the “Add connector” experience in Claude or ChatGPT just work, login window included. The issued token is a regular MARS JWT, so OAuth and static Bearer tokens coexist.
- Reverse proxy and tunnel friendly — public URLs honor the
X-Forwarded-*headers, so exposing a development server through ngrok, or a production one behind nginx or IIS, needs no extra code.
The Demos/MCPServer project shows all of this: public tools, FireDAC-backed authenticated tools and the OAuth flow. Details are in the MCP documentation page.
An AI assistant that knows MARS
The other side of the AI coin: MARS now ships Agent Skills for Claude Code and other AI coding agents. They teach the assistant how MARS works — scaffolding a new server, writing resources, securing endpoints, publishing datasets, building MCP servers — so the code it writes looks like code you would write.
From Claude Code:
/plugin marketplace add andrea-magni/MARS
/plugin install mars-curiosity@mars
or, for any tool supporting skills, npx skills add andrea-magni/MARS. See the Agent Skills guide.
A real documentation site
Documentation has been the most frequent request over the years. MARS now has a proper documentation site: getting started guide, server and client reference, a page for each major feature (authentication, authorization, FireDAC, serialization, SSE, templates, OpenAPI, logging, MCP), the demo index and a step-by-step Tailwind CSS tutorial.
Server-Sent Events, WebStencils and htmx
MARS is not only about JSON APIs:
- Server-Sent Events are supported on the server side, and the new
TMARSClientResourceSSEcomponent consumes them from Delphi clients.SSEDemoincludes both a plain HTML+JS page and an FMX client. - WebStencils integration brings server-side HTML templating to MARS resources. Combined with htmx you can build dynamic web UIs with very little JavaScript: see
WebStencilsDemo,HtmxDemoand the newTailwindcssDemo.
HTTP and API design
- The
QUERYHTTP verb — safe and idempotent likeGET, but with a request body: ideal for complex searches. Supported on both the server ([QUERY]) and the client side. HEADrequests onTFileSystemResourceand descendants.- Bulk parameter binding —
[QueryParams],[PathParams],[Headers]and[Cookies]inject whole sets of values at once;IMARSRequestgainedGetHeaders. - Richer OpenAPI output — much more of the specification can now be expressed through attributes on data types, parameters and request bodies.
- CORS — support for
Access-Control-Allow-Private-Network(CORS.PrivateNetworkparameter).
Serialization, logging, client
- New
[JSONSkip]and[JSONSkipEmptyValues]attributes, and serialization options applied more consistently across the library; support forTList<TPair<string,T>>and dictionaries; new array-of-record helpers. TMARSReqRespLoggerJSONwrites request/response logs as JSON lines, ready for Grafana-style tooling, withNoLogsupport to keep sensitive endpoints out of the logs.- A new
TMARSHttpClientimplementation for Delphi 13 and later, and a simplerPost(TStream)overload. - New demos:
OTPDemo(TOTP two-factor authentication with cross-platform SVG QR codes) andTokenRenew(automatic token renewal).
Security and robustness — please upgrade
This release fixes a path traversal issue in TFileSystemResource (#195). If you expose files through it, upgrading is strongly recommended.
Request paths are now validated segment by segment before the file system is touched, and the canonical result must still lie under the root folder. As a consequence . and .. segments are rejected by default. If your clients legitimately send them (browsers collapse them before sending, other HTTP clients may not), opt in with the new [DotSegments] attribute: dot-segments are accepted, but the path can never climb above the root folder — not even halfway through (#204).
[Path('www/{*}'), RootFolder('{bin}\www', True), DotSegments]
TWebResource = class(TFileSystemResource)
end;
Other hardening worth mentioning:
- New projects generated by MARSCmd/MARSTemplate get their own random JWT secret instead of relying on a default (#201, #202).
- Malformed request bodies now answer 400 instead of 500; status code, reason and content type are preserved through exception handling.
- Repeated query parameter names no longer cause a 500 (#196); the in-memory logger is no longer always on once its unit is included (#197).
- Many JSON fixes (empty values and missing members, records with object members, null handling, a nasty infinite recursion) and JWT fixes (base64url payloads without padding, invalid tokens no longer raising exceptions).
Under the hood the test suite grew considerably — request/response mocks, a suite exercising the default engine, no more memory leaks in tests — which is what made this amount of change possible with confidence.
Compatibility
MARS 1.7 supports Delphi versions from 10.4 up to Delphi 13.1 Florence, on Windows and Linux. Packages for 13.1 are included; mORMot sources and DCS have been synced to recent versions.
Thank you
This release includes patches, reports and ideas from Nando Dessena, Marco Ferlini, Ertan Küçükoglu and Holger Flick. Thank you — and thanks to everyone opening issues and using MARS in production.
Get it
- Download the installer or the sources from the GitHub releases page.
- Start from the installation guide and bootstrap a project with MARSCmd.
- Try the MCP demo, connect your favorite AI agent to it, and let me know what you build.