Conversation
Define SSE event payloads, identifier semantics, and security/disambiguation guardrails so gateway and MCP changes can be implemented deterministically. Made-with: Cursor
Require bearer auth for /mcp access, bind sessions to caller identity, enforce TTL/session caps, and add tests covering unauthorized access and expired-session behavior. Made-with: Cursor
Add shared course/listing resolvers with format validation, deterministic latest-term selection, explicit ambiguity errors, and normalized identifier fields in tool responses. Made-with: Cursor
Introduce external user identity mapping in the engine schema and enforce authenticated ownership for schedule-related MCP tools to prevent cross-user data access. Made-with: Cursor
Create a dedicated Python gateway that streams chat events, calls Junction MCP tools over HTTP with session management, handles timeout/cancel paths, and includes stream behavior tests. Made-with: Cursor
Add an authenticated SvelteKit proxy endpoint to the FastAPI gateway, ship an Ask AI page that renders SSE output in real time, and expose entry navigation from the app header. Made-with: Cursor
Include request/session tracing in gateway and MCP flows, ship a smoke-test script, and document operational checks, failure modes, and staging sign-off steps. Made-with: Cursor
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b1794d08df
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| def _headers(self, include_session: bool) -> dict[str, str]: | ||
| headers = { | ||
| "content-type": "application/json", | ||
| "accept": "application/json, text/event-stream", | ||
| } | ||
| if self._settings.mcp_token: | ||
| headers["authorization"] = f"Bearer {self._settings.mcp_token}" | ||
| if include_session and self._session_id: |
There was a problem hiding this comment.
Forward external user id in MCP request headers
The gateway never forwards x-external-user-id when it calls Engine MCP, because _headers() only sets content/auth/session headers. In this commit, schedule/user tools authorize via authContext.externalUserId (mapped in external_user_identities), so calls coming through Ask Gateway will always be treated as missing user context and return auth errors instead of user schedules. Please thread the caller identity into MCP headers so mapped users can actually use schedule-scoped tools.
Useful? React with 👍 / 👎.
| : undefined; | ||
| const netid = typeof netidHeader === "string" && netidHeader.trim().length > 0 ? netidHeader.trim() : undefined; | ||
|
|
||
| const clientKey = externalUserId ?? netid ?? (bearerToken ? `token:${bearerToken.slice(0, 8)}` : "anonymous"); |
There was a problem hiding this comment.
Use full bearer token entropy for clientKey binding
Session binding and per-client limits currently key on bearerToken.slice(0, 8), which collapses many distinct bearer tokens (especially JWTs that share the same prefix) into the same clientKey. That makes MCP_MAX_SESSIONS_PER_CLIENT apply across unrelated callers and weakens the caller-session binding check when a session ID is exposed. Derive clientKey from the full token (or a stable hash of it) to avoid collisions.
Useful? React with 👍 / 👎.
… caching. Increase MAX_TOOL_ITERATIONS to 30 and improve code readability with consistent formatting. Add logging for tool fetching and implement a cache mechanism for tool responses.
|
and update to add fall 2026 |
What this PR does
Adds an end-to-end Ask AI backend path: Web -> Ask Gateway (FastAPI SSE) -> Engine MCP.
Hardens MCP security/session handling in Engine.
Adds deterministic MCP tool ID resolution and ambiguity-safe behavior.
Adds external identity mapping + ownership checks for user/schedule tools.
Adds initial web Ask AI route/page in this repo for local validation.
Adds observability, smoke test script, and runbook/checklist docs.
Key changes
Docs/Contracts
Added Ask AI contract and integration notes (docs/ask-ai-contract.md, apps/engine/api_specification.md).
Engine MCP hardening
Bearer auth (MCP_ACCESS_TOKEN), session TTL/caps, caller-session binding, structured auth errors.
Tool reliability
New shared resolver (apps/engine/src/mcp/resolvers.ts) for courseId/listingId/code resolution + validation.
Identity/authorization
New external_user_identities schema + migration.
Schedule tools now enforce mapped-user ownership checks.
Ask Gateway (new app)
FastAPI SSE endpoint, MCP HTTP client/session flow, timeout/cancel handling.
.env autoload support via python-dotenv.
Web integration (local in this repo)
Ask stream proxy route + /ask-ai page + header entry point.
Ops/verification
Added smoke script + runbook with staging checklist.
Testing performed
Engine DB migrations applied locally (Docker Postgres/Redis).
Engine MCP tests: 11 passed / 0 failed (with local env + Docker).
Ask Gateway tests: 3 passed / 0 failed.
Manual curl SSE validation confirms:
status -> tool_call -> tool_result -> token -> done sequence
gateway->engine auth path functioning after .env autoload fix.
Notes / known limitations
Current Ask Gateway response logic is still rule-based and minimal (tool loop works, full LLM reasoning/schedule writes are not yet implemented).
Web svelte-check has existing unrelated project errors; not introduced by this PR.