Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 9 additions & 7 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ ENVIRONMENT='dev'

APP_ENV='development'
LIFECYCLE_MODE='all'
# Public UI origin used by host preview auth bootstrap redirects.
# Public UI origin used by user-facing links and host preview auth bootstrap redirects.
LIFECYCLE_UI_URL=
# Public preview host suffix, for URLs like https://3000--<slug>.preview.lifecycle.dev/.
CHAT_PREVIEW_DOMAIN=
Expand All @@ -75,12 +75,14 @@ KEYCLOAK_ISSUER=
KEYCLOAK_ISSUER_INTERNAL=
KEYCLOAK_CLIENT_ID=
KEYCLOAK_JWKS_URL=

# MCP SERVER (remote Streamable HTTP endpoint at /mcp)
MCP_SERVER_ENABLED=false
# Canonical resource URL; MCP access tokens must carry this value in `aud`.
# Example: https://app.lifecycle.example.com/mcp
MCP_RESOURCE_URL=
# Optional explicit admin URL; otherwise derived from the internal issuer.
KEYCLOAK_ADMIN_BASE_URL=
# Web-only credential used to configure Lifecycle-owned MCP OAuth state.
KEYCLOAK_MANAGEMENT_CLIENT_ID=lifecycle-api-keycloak-management
KEYCLOAK_MANAGEMENT_CLIENT_SECRET=
# Worker-only credential used to inspect personal API-key owners.
KEYCLOAK_PRINCIPAL_SYNC_CLIENT_ID=lifecycle-api-principal-sync
KEYCLOAK_PRINCIPAL_SYNC_CLIENT_SECRET=

# LOCAL DEVELOPMENT
LOCAL_DEV_USER_ID=
Expand Down
5 changes: 5 additions & 0 deletions Tiltfile
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ ui_scheme = "https" if ngrok_ui_domain else "http"
keycloak_host = ngrok_keycloak_domain or "localhost:8081"
app_host = ngrok_domain or "localhost:5001"
ui_host = ngrok_ui_domain or "localhost:3000"
app_origin = "{}://{}".format(app_scheme, app_host)
company_idp_origin = "{}://{}".format(keycloak_scheme, keycloak_host)
internal_keycloak_origin = "http://lifecycle-keycloak-service.{}.svc.cluster.local:8080".format(app_namespace)

Expand Down Expand Up @@ -421,6 +422,10 @@ for r in lifecycle_deployment:
containers = r["spec"]["template"]["spec"].get("containers", [])
if len(containers) > 0:
container = containers[0]
# With ngrok, APP_HOST must be the ngrok origin so agents can reach Lifecycle MCP under the same OAuth resource identifier.
for env_var in (container.get("env") or []):
if env_var.get("name") == "APP_HOST":
env_var["value"] = app_origin
if container.get("volumeMounts") == None:
container["volumeMounts"] = []
container["volumeMounts"].append({
Expand Down
1 change: 1 addition & 0 deletions dd-trace.js → dd-trace-init.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

'use strict';

// Runtime TS loaders honor baseUrl, so a root dd-trace.js would shadow node_modules and make this preload require itself.
const tracer = require('dd-trace').init({
serviceMapping: {
redis: 'lifecycle-redis',
Expand Down
135 changes: 0 additions & 135 deletions docs/mcp-server.md

This file was deleted.

18 changes: 14 additions & 4 deletions helm/environments/local/lifecycle.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -122,10 +122,13 @@ components:
value: '80'
- name: DD_TRACE_ENABLED
value: 'false'
- name: MCP_SERVER_ENABLED
value: 'true'
- name: MCP_RESOURCE_URL
value: http://localhost:5001/mcp
- name: KEYCLOAK_MANAGEMENT_CLIENT_ID
value: lifecycle-api-keycloak-management
- name: KEYCLOAK_MANAGEMENT_CLIENT_SECRET
valueFrom:
secretKeyRef:
name: lifecycle-keycloak-api-keycloak-management
key: clientSecret
ports:
- name: http
containerPort: 80
Expand Down Expand Up @@ -185,6 +188,13 @@ components:
value: '10000'
- name: DD_TRACE_ENABLED
value: 'false'
- name: KEYCLOAK_PRINCIPAL_SYNC_CLIENT_ID
value: lifecycle-api-principal-sync
- name: KEYCLOAK_PRINCIPAL_SYNC_CLIENT_SECRET
valueFrom:
secretKeyRef:
name: lifecycle-keycloak-api-principal-sync
key: clientSecret
ports:
- name: http
containerPort: 80
Expand Down
10 changes: 5 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@
],
"scripts": {
"babel-node": "babel-node --extensions '.ts'",
"dev": "LOG_LEVEL=${LOG_LEVEL:-info} ts-node -r ./dd-trace.js -r tsconfig-paths/register --project tsconfig.server.json ws-server.ts | pino-pretty -c -t HH:MM -i pid,hostname,filename -o '{msg}'",
"dev": "LOG_LEVEL=${LOG_LEVEL:-info} ts-node -r ./dd-trace-init.js -r tsconfig-paths/register --project tsconfig.server.json ws-server.ts | pino-pretty -c -t HH:MM -i pid,hostname,filename -o '{msg}'",
"build": "next build && tsc --project tsconfig.server.json && tsc-alias -p tsconfig.server.json",
"build:local": "next build --no-lint && tsc --project tsconfig.server.json && tsc-alias -p tsconfig.server.json",
"start": "NEXT_MANUAL_SIG_HANDLE=true NODE_ENV=production node -r ./dd-trace.js .next/ws-server.js",
"start": "NEXT_MANUAL_SIG_HANDLE=true NODE_ENV=production node -r ./dd-trace-init.js .next/ws-server.js",
"run-prod": "port=5001 pnpm run start",
"knex": "pnpm run knex",
"test": "NODE_ENV=test jest --maxWorkers=75% && node --test sysops/workspace-gateway/*.test.mjs",
Expand All @@ -26,9 +26,7 @@
"prepare": "husky install",
"generate:jsonschemas": "tsx ./scripts/generateSchemas.ts generatejson",
"generate:yamls": "tsx ./scripts/generateSchemas.ts generateyaml",
"generate:schemas": "pnpm run generate:jsonschemas && pnpm run generate:yamls",
"eval:baseline": "ts-node eval/baseline/captureBaseline.ts",
"eval:compare": "ts-node eval/compare.ts"
"generate:schemas": "pnpm run generate:jsonschemas && pnpm run generate:yamls"
},
"dependencies": {
"@ai-sdk/anthropic": "^4.0.0",
Expand All @@ -43,6 +41,8 @@
"@octokit/core": "^5.0.2",
"@octokit/webhooks": "^12.0.1",
"ai": "^7.0.0",
"ajv": "^8.17.1",
"ajv-formats": "^3.0.1",
"aws-sdk": "^2.1004.0",
"bullmq": "5.56.8",
"cockatiel": "^3.2.1",
Expand Down
6 changes: 6 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,6 @@ describe('GET /api/v2/ai/agent/mcp-connections/[slug]/oauth/callback', () => {
serverUrl: 'https://mcp.example.com/v1/mcp',
authorizationCode: 'sample-code',
callbackState: 'flow-123.sample-state',
scope: 'sample.read',
})
);
expect(mockDiscoverTools).toHaveBeenCalledWith(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -423,7 +423,6 @@ const getHandler = async (req: NextRequest, { params }: { params: Promise<{ slug
serverUrl: transport.url,
authorizationCode: code,
callbackState,
scope: authConfig.scope,
});

const validatedAt = new Date().toISOString();
Expand Down
Loading
Loading