Skip to content

Commit 2aadcdb

Browse files
author
Růžička, David
committed
Merge branch 'dr-add-additional-profile-description' into 'main'
feat(03.2): add admin profile descriptions via MCP4_PROFILES_DESCRIPTION See merge request ai-adoption/mcp/mcp4openapi!12
2 parents dd04928 + b32ebdc commit 2aadcdb

24 files changed

Lines changed: 3570 additions & 15 deletions

.planning/PROJECT.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ authenticate, authorize, audit, and proxy every tool call in the company.
3939
- ✓ Upstream tool discovery and proxy (Phase 02) - `tools/list` and `tools/call` forwarded to correct upstream provider; upstream tools namespaced by provider; `NotificationQueue` with TTL eviction for `tools/list_changed` replay on reconnect; `sendToClient` SSE real-time dispatch
4040
- ✓ API key authentication gate (Phase 03) - inbound M2M clients validated via inline env-var API keys before session establishment; `ClientAuthGate` runs after enterprise auth, before any upstream connection; `SessionData.clientPrincipal` populated with resolved identity (`subject`, `authType`, `scopes`); HMAC-SHA256 timing-safe comparison; fail-fast profile-load validator
4141
- ✓ upstream_mcp singular constraint (Phase 03.1) - Profile.upstream_mcp narrowed from UpstreamMcpServerConfig[] to UpstreamMcpServerConfig; Zod schema rejects array shape at parse time with migration hint; all call sites (mcp-server.ts, http-transport.ts, profile-resolver.ts) narrowed; BREAKING CHANGE: profile JSON must use `upstream_mcp: {...}` not `upstream_mcp: [{...}]`
42+
- ✓ Admin-supplied HTML profile descriptions (Phase 03.2) - `MCP4_PROFILES_DESCRIPTION` env var (JSON object: profile key → HTML string) parsed once at startup; keys matched against profileId/profileName/aliases; resolved adminDescription stored per-profile and rendered raw (no escaping) in HTML index detail card before the profile's own description; duplicate-key resolution and invalid JSON cause process exit at startup (fail-fast); sidebar list view unchanged
4243

4344
### Active
4445
- [ ] Upstream tool discovery and proxy - tools/list and tools/call forwarded to correct upstream
@@ -110,7 +111,7 @@ authenticate, authorize, audit, and proxy every tool call in the company.
110111
| Tool namespacing by upstream provider | Prevents tool name collisions across providers; makes audit logs and policy rules unambiguous | - Pending |
111112

112113
---
113-
*Last updated: 2026-05-02 after Phase 03.1 completion — upstream_mcp narrowed from array to singular; BREAKING CHANGE for profile JSON format*
114+
*Last updated: 2026-05-03 after Phase 03.2 completion — MCP4_PROFILES_DESCRIPTION env var for admin HTML profile descriptions; fail-fast startup validation; raw-HTML rendering in detail card*
114115

115116
## Evolution
116117

.planning/ROADMAP.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,18 @@ Plans:
7070
- [x] 03-02-PLAN.md - ApiKeyStore interface, InlineApiKeyStore, and factory (AUTH-02; SasankaApiKeyStore deferred to Phase 4)
7171
- [x] 03-03-PLAN.md - ClientAuthGate orchestrator (API key path only), http-transport wiring, session clientPrincipal attachment (AUTH-02, AUTH-03)
7272

73+
### Phase 03.2: Profile env-var description field (INSERTED)
74+
75+
**Goal:** Add optional admin-supplied HTML description per profile via a server-wide `MCP4_PROFILES_DESCRIPTION` env var (JSON map of profile-id/name/alias → HTML string). Description renders raw (no sanitization) in the HTML index detail card immediately before the profile's own description. Sidebar list view is unchanged. Fail-fast at startup on invalid JSON or duplicate-resolution conflicts.
76+
**Requirements**: TBD (locked decisions D-01..D-12 in 03.2-CONTEXT.md serve as acceptance criteria)
77+
**Depends on:** Phase 03
78+
**Plans:** 3/3 plans complete
79+
80+
Plans:
81+
- [x] 03.2-01-PLAN.md — Pure module: parseProfilesDescriptionEnv + resolveProfileAdminDescriptions helpers + unit tests (D-01..D-09)
82+
- [x] 03.2-02-PLAN.md — Wiring: buildProfileIndexPayload 4th-arg adminDescriptions + HttpTransport.setProfileAdminDescriptions setter + main() startup parse/resolve/setter (D-01, D-04, D-05, D-07..D-10)
83+
- [x] 03.2-03-PLAN.md — HTML template patch: raw-HTML adminDescription div in renderDetail before profile.description; sidebar untouched; end-to-end raw-HTML pass-through tests (D-06, D-10, D-11, D-12)
84+
7385
### Phase 03.1: Odstranění multi upstream mcp supportu (INSERTED)
7486

7587
**Goal**: Profile.upstream_mcp narrowed end-to-end from UpstreamMcpServerConfig[] to UpstreamMcpServerConfig (singular). The runtime single-provider constraint already exists in profile-loader (D-03 check); this phase relocates it into the type system (Zod + TS), removes the now-dead loader runtime check, and migrates all consumers + test fixtures to the singular shape. Breaking change for end-user profile JSON/YAML using array syntax.

.planning/STATE.md

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@ gsd_state_version: 1.0
33
milestone: v1.0
44
milestone_name: milestone
55
status: Ready to plan
6-
stopped_at: Phase 03.2 context gathered
7-
last_updated: "2026-05-03T20:29:04.939Z"
6+
stopped_at: Completed 03.2-03-PLAN.md
7+
last_updated: "2026-05-03T22:56:32.129Z"
88
progress:
99
total_phases: 7
10-
completed_phases: 4
11-
total_plans: 14
12-
completed_plans: 14
10+
completed_phases: 5
11+
total_plans: 17
12+
completed_plans: 17
1313
---
1414

1515
# Project State
@@ -19,11 +19,11 @@ progress:
1919
See: .planning/PROJECT.md (updated 2026-03-26)
2020

2121
**Core value:** A security boundary between internal AI clients and all upstream MCP servers - one place to authenticate, authorize, audit, and proxy every tool call.
22-
**Current focus:** Phase 03.1odstran-n-multi-upstream-mcp-supportu
22+
**Current focus:** Phase 03.2profile-env-var-description
2323

2424
## Current Position
2525

26-
Phase: 4
26+
Phase: 04
2727
Plan: Not started
2828

2929
## Performance Metrics
@@ -59,6 +59,9 @@ Plan: Not started
5959
| Phase 03-client-authentication-gate P03 | 10min | 3 tasks | 6 files |
6060
| Phase 03.1-odstran-n-multi-upstream-mcp-supportu P01 | 5 | 3 tasks | 8 files |
6161
| Phase 03.1-odstran-n-multi-upstream-mcp-supportu P02 | 8min | 3 tasks | 6 files |
62+
| Phase 03.2-profile-env-var-description P01 | 3min | 2 tasks | 2 files |
63+
| Phase 03.2-profile-env-var-description P02 | 4min | 3 tasks | 4 files |
64+
| Phase 03.2-profile-env-var-description P03 | 5min | 2 tasks | 2 files |
6265

6366
## Accumulated Context
6467

@@ -98,6 +101,11 @@ Recent decisions affecting current work:
98101
- [Phase 03.1-odstran-n-multi-upstream-mcp-supportu]: validateUpstreamProvider path changed to 'upstream_mcp' (no [N] index) - all error paths are now upstream_mcp.transport.url, upstream_mcp.auth.header_name, etc.
99102
- [Phase 03.1-odstran-n-multi-upstream-mcp-supportu]: hasUpstreamMcpFlag lives in upstream-mcp-config.ts (semantic owner of all upstream_mcp logic) not profile-resolver.ts
100103
- [Phase 03.1-odstran-n-multi-upstream-mcp-supportu]: Legacy-array tolerance preserved at MIGRATION-CLEANUP sites: env-var collector (reads raw JSON pre-Zod) and hasUpstreamMcpFlag (list-view UX) for migration period
104+
- [Phase 03.2-profile-env-var-description]: Parse-time D-05 conflict detection skipped: profile list unavailable at parse time; deferred to resolveProfileAdminDescriptions which receives both map and profiles
105+
- [Phase 03.2-profile-env-var-description]: adminDescription field rides inside existing safeJsonForHtml(enriched) blob — no separate template variable needed; Plan 03 reads it client-side from the JSON payload
106+
- [Phase 03.2-profile-env-var-description]: null -> undefined conversion at HttpTransport call site (this.profileAdminDescriptions ?? undefined) so setter accepts Map|null while buildProfileIndexPayload signature uses Map|undefined
107+
- [Phase 03.2-profile-env-var-description]: Admin description inserted between profile-title and profile-subtitle via ternary (not ||) — both undefined and empty string suppress the div
108+
- [Phase 03.2-profile-env-var-description]: safeJsonForHtml escapes only '<' not '>'; test assertions must use literal '>' for tag closings in expected rendered output
101109

102110
### Roadmap Evolution
103111

@@ -116,6 +124,6 @@ None yet.
116124

117125
## Session Continuity
118126

119-
Last session: 2026-05-03T20:29:04.935Z
120-
Stopped at: Phase 03.2 context gathered
121-
Resume file: .planning/phases/03.2-profile-env-var-description/03.2-CONTEXT.md
127+
Last session: 2026-05-03T22:51:53.266Z
128+
Stopped at: Completed 03.2-03-PLAN.md
129+
Resume file: None

.planning/phases/03.2-profile-env-var-description/.gitkeep

Whitespace-only changes.

0 commit comments

Comments
 (0)