A local Model Context Protocol (MCP) server that exposes the OutSystems LifeTime REST API v2 as conversational tools.
Connect it to Claude Desktop (or any MCP-compatible client) and manage deployments, users, teams and applications through natural language.
Unofficial community project — not affiliated with or endorsed by OutSystems. It drives a powerful administrative API (it can create deployments, modify users, edit database connections and more). Read the Security section before using it.
66 tools across 10 domains, covering the LifeTime REST API v2:
| Domain | Tools | Examples |
|---|---|---|
| Environments | 10 | get_environments, create_environment, set_maintenance_mode |
| Applications | 7 | get_applications, get_application_dependencies, tag_running_version |
| Deployments | 7 | create_deployment, execute_deployment_command, get_deployment_status |
| Users | 7 | list_users, create_user, update_user |
| Teams | 7 | list_teams, manage_team_users, manage_team_apps |
| Roles | 6 | list_roles, create_role, manage_user_app_role |
| Modules | 4 | list_modules, get_module_version |
| DB connections | 12 | list_db_connections, update_db_connection, test_db_connection |
| Configurations | 3 | get_application_configurations, update_application_configurations |
| Operations | 3 | cleanup_old_deployment_plans, get_application_consumers |
- Docker (recommended) — no Node.js install required on the host
- An OutSystems LifeTime instance (version 11)
- A Service Account token — create one in LifeTime → User Management → Service Accounts
docker build -t outsystems-lifetime-mcp .# Should print the FATAL env-var error and exit 1 — that means the binary works
docker run --rm outsystems-lifetime-mcpOpen (or create) the Claude Desktop config file:
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Windows:
%APPDATA%\Claude\claude_desktop_config.json
Add the server entry under "mcpServers":
{
"mcpServers": {
"outsystems-lifetime": {
"command": "docker",
"args": [
"run", "--rm", "-i",
"-e", "LIFETIME_BASE_URL",
"-e", "LIFETIME_API_TOKEN",
"outsystems-lifetime-mcp"
],
"env": {
"LIFETIME_BASE_URL": "https://your-lifetime.example.com/lifetimeapi/rest/v2",
"LIFETIME_API_TOKEN": "your-service-account-token"
}
}
}
}The
-iflag is required — it keeps stdin open so the MCP stdio protocol flows through Docker correctly.
The-eflags forward the env vars from the Claude Desktop process into the container.
- Restart Claude Desktop — the tools will appear in the tools panel.
# Install dependencies and compile
npm install
npm run build
# Run
LIFETIME_BASE_URL="https://your-lifetime.example.com/lifetimeapi/rest/v2" \
LIFETIME_API_TOKEN="your-service-account-token" \
node dist/index.jsClaude Desktop config for the Node.js variant:
{
"mcpServers": {
"outsystems-lifetime": {
"command": "node",
"args": ["/ABSOLUTE/PATH/TO/outsystems-lifetime-mcp/dist/index.js"],
"env": {
"LIFETIME_BASE_URL": "https://your-lifetime.example.com/lifetimeapi/rest/v2",
"LIFETIME_API_TOKEN": "your-service-account-token"
}
}
}
}You: What environments do I have?
Claude: [calls get_environments] → Development (key: abc-123), Quality (key: def-456), Production (key: ghi-789)
You: Deploy the latest version of "CustomerPortal" from Development to Quality.
Claude: [calls get_applications with IncludeEnvStatus=true]
[calls create_deployment with source=abc-123, target=def-456, version key]
[calls execute_deployment_command with command=start]
Deployment started! DeploymentKey: xyz-000
You: How's the deployment going?
Claude: [calls get_deployment_status] → running — "Publishing CustomerPortal..."
You: Done yet?
Claude: [calls get_deployment_status] → finished_successful ✓
The server propagates the LifeTime Errors array verbatim when an API call fails.
For example, a 403 response surfaces as:
{
"errors": ["Invalid user permissions."],
"statusCode": 403
}This lets Claude explain exactly why an operation failed and suggest corrective actions.
| Variable | Required | Description |
|---|---|---|
LIFETIME_BASE_URL |
✅ | Full base URL of the LifeTime API, e.g. https://lt.example.com/lifetimeapi/rest/v2 |
LIFETIME_API_TOKEN |
✅ | Bearer token from a LifeTime Service Account |
src/
index.ts Entry point — env validation, server wiring, transport
registry.ts Tool registry: maps domains → tools + handlers
types.ts Shared composition types (ToolModule, HandlerMap)
api-client.ts Axios client with auth + LifeTime error extraction
schemas.ts Zod schemas for input validation
tool-helpers.ts Shared runTool wrapper & result type
http-server.ts Streamable HTTP transport (optional, for remote access)
registry.test.ts Registry integrity tests (node:test)
tools/ One module per domain — environments, applications,
users, teams, deployments, roles, modules,
db-connections, configurations, operations
dist/ Compiled output (after npm run build)
reference/ Vendored LifeTime REST API v2 Swagger spec (schema source)
npm run typecheck # type-check without emitting
npm test # registry integrity tests (node:test)
npm run build # compile to dist/
# Run directly with tsx (no compile step)
LIFETIME_BASE_URL=... LIFETIME_API_TOKEN=... npm run devThe enforced boundary is the LifeTime Service Account, not the AI. Per the OutSystems docs, a Service Account "follows the same permission model of regular user accounts, using roles and teams," and all API operations are limited to the permissions associated with that account, enforced by LifeTime server-side. The server can never perform an operation the account isn't granted, and it cannot escalate its own access. Scope the account, and you've scoped the tool.
- Least privilege is the primary control. Create a dedicated Service Account and assign it a role scoped to exactly what you need — e.g. read-only, or only specific environments (application/deployment permissions are per-environment; DB-connection permissions are set at the environment level). Exclude user/role management if you don't need it. Whatever the role can't do, the AI can't do.
- Audited & traceable. Every REST call is audited and traceable to the Service Account, viewable in its activity log in LifeTime. Nothing happens off the record.
- Revocable tokens. Service Account tokens are time-bound (6/12/24 months) and can
be invalidated instantly. Treat the token as a credential: keep it in
.env(gitignored) or your client's secret store, never commit it, and rotate if exposed. - Lock down HTTP mode. The optional Streamable HTTP transport must run behind
HTTP_BEARER_TOKEN; never expose an unauthenticated endpoint to a network or tunnel. - Prefer non-production first. Point it at a Development/Test LifeTime before trusting it against Production.
Several tools perform destructive or irreversible actions (e.g. create_deployment /
execute_deployment_command, create_user / update_user, delete_role,
update_db_connection, set_maintenance_mode) — the Service Account's role is what
gates access to them.
A note on "human in the loop": most MCP clients prompt before running a tool, which is a useful extra layer — but it's a client-side setting (auto-approve disables it), not something this server enforces. Don't rely on it as your primary control; rely on the Service Account's scoped permissions, which are enforced server-side and audited.
No credentials are logged, and the server only talks to the LifeTime URL you configure.
- OutSystems 11 (O11) self-managed / cloud, via the LifeTime REST API v2
(
/lifetimeapi/rest/v2). Schemas were derived from the v2 Swagger spec inreference/. - Not for OutSystems Developer Cloud (ODC) — ODC has its own APIs and MCP tooling (see below).
- Requires Node.js >= 18 (or Docker).
The OutSystems MCP space is split between ODC (cloud) and LifeTime / O11 (self-managed). Most tooling targets ODC; this project focuses on LifeTime.
| Project | Target | Approach |
|---|---|---|
| this project | LifeTime / O11 | Official REST API v2 — full read/write, 66 tools |
| OutSystems/outsystems-mcp | ODC | Official remote MCP |
| rpgomes-code/outsystems-mcp-extended | ODC | Community server wrapping ODC REST APIs |
Not to be confused with the unrelated Forge component also named "MCP Server (O11)", which turns an O11 app into an MCP endpoint rather than managing LifeTime.
See CONTRIBUTING.md for the dev workflow and how to add tools.
MIT © Paulo Ricardo Monteiro