{"id":50399036,"url":"https://github.com/promonteiro89/o11-lt-mcp","last_synced_at":"2026-05-30T22:02:32.010Z","repository":{"id":361398651,"uuid":"1254309714","full_name":"promonteiro89/o11-lt-mcp","owner":"promonteiro89","description":"MCP server exposing the OutSystems LifeTime REST API v2 as conversational tools — manage deployments, environments, users, teams, roles and applications (66 tools).","archived":false,"fork":false,"pushed_at":"2026-05-30T13:12:42.000Z","size":82,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-30T14:10:15.932Z","etag":null,"topics":["claude","devops","lifetime","mcp","model-context-protocol","outsystems","typescript"],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/promonteiro89.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-30T12:06:35.000Z","updated_at":"2026-05-30T12:24:54.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/promonteiro89/o11-lt-mcp","commit_stats":null,"previous_names":["promonteiro89/o11-lt-mcp"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/promonteiro89/o11-lt-mcp","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/promonteiro89%2Fo11-lt-mcp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/promonteiro89%2Fo11-lt-mcp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/promonteiro89%2Fo11-lt-mcp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/promonteiro89%2Fo11-lt-mcp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/promonteiro89","download_url":"https://codeload.github.com/promonteiro89/o11-lt-mcp/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/promonteiro89%2Fo11-lt-mcp/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33711018,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-05-30T02:00:06.278Z","response_time":92,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["claude","devops","lifetime","mcp","model-context-protocol","outsystems","typescript"],"created_at":"2026-05-30T22:02:29.734Z","updated_at":"2026-05-30T22:02:32.000Z","avatar_url":"https://github.com/promonteiro89.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# OutSystems LifeTime MCP Server\n\n[![CI](https://github.com/promonteiro89/o11-lt-mcp/actions/workflows/ci.yml/badge.svg)](https://github.com/promonteiro89/o11-lt-mcp/actions/workflows/ci.yml)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)\n[![Node.js](https://img.shields.io/badge/Node.js-%3E%3D18-339933?logo=node.js\u0026logoColor=white)](https://nodejs.org)\n[![TypeScript](https://img.shields.io/badge/TypeScript-strict-3178C6?logo=typescript\u0026logoColor=white)](https://www.typescriptlang.org)\n[![MCP](https://img.shields.io/badge/MCP-server-000000)](https://modelcontextprotocol.io)\n\nA local [Model Context Protocol](https://modelcontextprotocol.io) (MCP) server that exposes the **OutSystems LifeTime REST API v2** as conversational tools.  \nConnect it to Claude Desktop (or any MCP-compatible client) and manage deployments, users, teams and applications through natural language.\n\n\u003e **Unofficial community project** — not affiliated with or endorsed by OutSystems.\n\u003e It drives a powerful administrative API (it can create deployments, modify users, edit\n\u003e database connections and more). **Read the [Security](#security) section before using it.**\n\n---\n\n## Tools provided\n\n66 tools across 10 domains, covering the LifeTime REST API v2:\n\n| Domain | Tools | Examples |\n|---|---:|---|\n| Environments | 10 | `get_environments`, `create_environment`, `set_maintenance_mode` |\n| Applications | 7 | `get_applications`, `get_application_dependencies`, `tag_running_version` |\n| Deployments | 7 | `create_deployment`, `execute_deployment_command`, `get_deployment_status` |\n| Users | 7 | `list_users`, `create_user`, `update_user` |\n| Teams | 7 | `list_teams`, `manage_team_users`, `manage_team_apps` |\n| Roles | 6 | `list_roles`, `create_role`, `manage_user_app_role` |\n| Modules | 4 | `list_modules`, `get_module_version` |\n| DB connections | 12 | `list_db_connections`, `update_db_connection`, `test_db_connection` |\n| Configurations | 3 | `get_application_configurations`, `update_application_configurations` |\n| Operations | 3 | `cleanup_old_deployment_plans`, `get_application_consumers` |\n\n---\n\n## Prerequisites\n\n- **Docker** (recommended) — no Node.js install required on the host\n- An OutSystems **LifeTime** instance (version 11)\n- A **Service Account token** — create one in LifeTime → *User Management → Service Accounts*\n\n---\n\n## Docker setup (recommended)\n\n### 1. Build the image\n\n```bash\ndocker build -t outsystems-lifetime-mcp .\n```\n\n### 2. Smoke-test it\n\n```bash\n# Should print the FATAL env-var error and exit 1 — that means the binary works\ndocker run --rm outsystems-lifetime-mcp\n```\n\n### 3. Connect to Claude Desktop\n\nOpen (or create) the Claude Desktop config file:\n- **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`\n- **Windows**: `%APPDATA%\\Claude\\claude_desktop_config.json`\n\nAdd the server entry under `\"mcpServers\"`:\n\n```json\n{\n  \"mcpServers\": {\n    \"outsystems-lifetime\": {\n      \"command\": \"docker\",\n      \"args\": [\n        \"run\", \"--rm\", \"-i\",\n        \"-e\", \"LIFETIME_BASE_URL\",\n        \"-e\", \"LIFETIME_API_TOKEN\",\n        \"outsystems-lifetime-mcp\"\n      ],\n      \"env\": {\n        \"LIFETIME_BASE_URL\": \"https://your-lifetime.example.com/lifetimeapi/rest/v2\",\n        \"LIFETIME_API_TOKEN\": \"your-service-account-token\"\n      }\n    }\n  }\n}\n```\n\n\u003e The `-i` flag is required — it keeps stdin open so the MCP stdio protocol flows through Docker correctly.  \n\u003e The `-e` flags forward the env vars from the Claude Desktop process into the container.\n\n4. **Restart Claude Desktop** — the tools will appear in the tools panel.\n\n---\n\n## Local Node.js setup (alternative, no Docker)\n\n```bash\n# Install dependencies and compile\nnpm install\nnpm run build\n\n# Run\nLIFETIME_BASE_URL=\"https://your-lifetime.example.com/lifetimeapi/rest/v2\" \\\nLIFETIME_API_TOKEN=\"your-service-account-token\" \\\nnode dist/index.js\n```\n\nClaude Desktop config for the Node.js variant:\n\n```json\n{\n  \"mcpServers\": {\n    \"outsystems-lifetime\": {\n      \"command\": \"node\",\n      \"args\": [\"/ABSOLUTE/PATH/TO/outsystems-lifetime-mcp/dist/index.js\"],\n      \"env\": {\n        \"LIFETIME_BASE_URL\": \"https://your-lifetime.example.com/lifetimeapi/rest/v2\",\n        \"LIFETIME_API_TOKEN\": \"your-service-account-token\"\n      }\n    }\n  }\n}\n```\n\n---\n\n## Example deployment workflow (conversational)\n\n```\nYou: What environments do I have?\nClaude: [calls get_environments] → Development (key: abc-123), Quality (key: def-456), Production (key: ghi-789)\n\nYou: Deploy the latest version of \"CustomerPortal\" from Development to Quality.\nClaude: [calls get_applications with IncludeEnvStatus=true]\n        [calls create_deployment with source=abc-123, target=def-456, version key]\n        [calls execute_deployment_command with command=start]\n        Deployment started! DeploymentKey: xyz-000\n\nYou: How's the deployment going?\nClaude: [calls get_deployment_status] → running — \"Publishing CustomerPortal...\"\n\nYou: Done yet?\nClaude: [calls get_deployment_status] → finished_successful ✓\n```\n\n---\n\n## Error handling\n\nThe server propagates the LifeTime `Errors` array verbatim when an API call fails.  \nFor example, a 403 response surfaces as:\n\n```json\n{\n  \"errors\": [\"Invalid user permissions.\"],\n  \"statusCode\": 403\n}\n```\n\nThis lets Claude explain exactly why an operation failed and suggest corrective actions.\n\n---\n\n## Environment variables\n\n| Variable | Required | Description |\n|---|---|---|\n| `LIFETIME_BASE_URL` | ✅ | Full base URL of the LifeTime API, e.g. `https://lt.example.com/lifetimeapi/rest/v2` |\n| `LIFETIME_API_TOKEN` | ✅ | Bearer token from a LifeTime Service Account |\n\n---\n\n## Project structure\n\n```\nsrc/\n  index.ts            Entry point — env validation, server wiring, transport\n  registry.ts         Tool registry: maps domains → tools + handlers\n  types.ts            Shared composition types (ToolModule, HandlerMap)\n  api-client.ts       Axios client with auth + LifeTime error extraction\n  schemas.ts          Zod schemas for input validation\n  tool-helpers.ts     Shared runTool wrapper \u0026 result type\n  http-server.ts      Streamable HTTP transport (optional, for remote access)\n  registry.test.ts    Registry integrity tests (node:test)\n  tools/              One module per domain — environments, applications,\n                      users, teams, deployments, roles, modules,\n                      db-connections, configurations, operations\ndist/                 Compiled output (after npm run build)\nreference/            Vendored LifeTime REST API v2 Swagger spec (schema source)\n```\n\n---\n\n## Development\n\n```bash\nnpm run typecheck   # type-check without emitting\nnpm test            # registry integrity tests (node:test)\nnpm run build       # compile to dist/\n\n# Run directly with tsx (no compile step)\nLIFETIME_BASE_URL=... LIFETIME_API_TOKEN=... npm run dev\n```\n\n---\n\n## Security\n\n**The enforced boundary is the LifeTime Service Account, not the AI.** Per the\n[OutSystems docs](https://success.outsystems.com/Documentation/11_x_platform/Reference/OutSystems_APIs/LifeTime_API_v2/REST_API_Authentication),\na Service Account \"follows the same permission model of regular user accounts, using\nroles and teams,\" and **all API operations are limited to the permissions associated\nwith that account, enforced by LifeTime server-side**. The server can never perform an\noperation the account isn't granted, and it cannot escalate its own access. Scope the\naccount, and you've scoped the tool.\n\n- **Least privilege is the primary control.** Create a dedicated Service Account and\n  assign it a role scoped to exactly what you need — e.g. read-only, or only specific\n  environments (application/deployment permissions are per-environment; DB-connection\n  permissions are set at the environment level). Exclude user/role management if you\n  don't need it. Whatever the role can't do, the AI can't do.\n- **Audited \u0026 traceable.** Every REST call is audited and traceable to the Service\n  Account, viewable in its activity log in LifeTime. Nothing happens off the record.\n- **Revocable tokens.** Service Account tokens are time-bound (6/12/24 months) and can\n  be invalidated instantly. Treat the token as a credential: keep it in `.env`\n  (gitignored) or your client's secret store, never commit it, and rotate if exposed.\n- **Lock down HTTP mode.** The optional Streamable HTTP transport must run behind\n  `HTTP_BEARER_TOKEN`; never expose an unauthenticated endpoint to a network or tunnel.\n- **Prefer non-production first.** Point it at a Development/Test LifeTime before\n  trusting it against Production.\n\nSeveral tools perform destructive or irreversible actions (e.g. `create_deployment` /\n`execute_deployment_command`, `create_user` / `update_user`, `delete_role`,\n`update_db_connection`, `set_maintenance_mode`) — the Service Account's role is what\ngates access to them.\n\n\u003e **A note on \"human in the loop\":** most MCP clients prompt before running a tool, which\n\u003e is a useful extra layer — but it's a *client-side* setting (auto-approve disables it),\n\u003e not something this server enforces. Don't rely on it as your primary control; rely on\n\u003e the Service Account's scoped permissions, which are enforced server-side and audited.\n\nNo credentials are logged, and the server only talks to the LifeTime URL you configure.\n\n---\n\n## Compatibility\n\n- **OutSystems 11 (O11)** self-managed / cloud, via the **LifeTime REST API v2**\n  (`/lifetimeapi/rest/v2`). Schemas were derived from the v2 Swagger spec in\n  [`reference/`](reference/).\n- **Not** for **OutSystems Developer Cloud (ODC)** — ODC has its own APIs and MCP\n  tooling (see below).\n- Requires **Node.js \u003e= 18** (or Docker).\n\n---\n\n## Related projects\n\nThe OutSystems MCP space is split between **ODC** (cloud) and **LifeTime / O11**\n(self-managed). Most tooling targets ODC; this project focuses on **LifeTime**.\n\n| Project | Target | Approach |\n|---|---|---|\n| **this project** | LifeTime / O11 | Official REST API v2 — full read/write, 66 tools |\n| [OutSystems/outsystems-mcp](https://github.com/OutSystems/outsystems-mcp) | ODC | Official remote MCP |\n| [rpgomes-code/outsystems-mcp-extended](https://github.com/rpgomes-code/outsystems-mcp-extended) | ODC | Community server wrapping ODC REST APIs |\n\n\u003e Not to be confused with the unrelated Forge component also named *\"MCP Server (O11)\"*,\n\u003e which turns an O11 app into an MCP endpoint rather than managing LifeTime.\n\n---\n\n## Contributing\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md) for the dev workflow and how to add tools.\n\n---\n\n## License\n\n[MIT](LICENSE) © Paulo Ricardo Monteiro\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpromonteiro89%2Fo11-lt-mcp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpromonteiro89%2Fo11-lt-mcp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpromonteiro89%2Fo11-lt-mcp/lists"}