Conversation
…download in CI find on a non-existent subdirectory exits 1, which aborts the entrypoint under set -euo pipefail before mypy/pytest ever run. Fix: search from the base fastembed dir (always present after mkdir -p) with -path filters. Also skip the model download entirely in CI (GitHub Actions sets CI=true) — the ephemeral runner has no persistent cache and models are not needed for mypy or pytest.
fix: entrypoint find never fails under set -euo pipefail; skip model download in CI
- Bump _MCP_PROTOCOL_VERSION from 2025-03-26 to 2025-11-25 - Add description field to McpServerInfo (optional per new spec) - Add icon: NotRequired[str] to ACToolDef, ACResourceDef, ACResourceTemplate, and ACPromptDef (icon metadata support per new spec) - HTTP endpoint: validate Origin header → 403 for non-localhost origins (DNS rebinding protection, now a MUST per 2025-11-25 spec) - HTTP endpoint: validate MCP-Protocol-Version header → 400 for unsupported versions; absent header accepted for backwards compat (assume 2025-03-26) - HTTP endpoint: add GET /api/mcp → 405 so 2025-11-25 clients correctly identify this as Streamable HTTP (not the deprecated 2024-11-05 SSE transport) - Add 12 new tests covering protocol version, server description, Origin security, MCP-Protocol-Version header, and GET transport disambiguation Elicitation, sampling, roots, and experimental tasks are intentionally omitted — they are not applicable to this server's use case.
feat(mcp): upgrade to MCP 2025-11-25 spec compliance
- Replace "Cursor-free agent loop" with "agent loop" throughout Python docstrings and comments (agent_loop.py, agent_run.py, config.py, tools/__init__.py, github_mcp_client.py, models/__init__.py) - Delete docs/cursor-agent-spawning.md — describes Cursor's Task tool, which AgentCeption does not use; already marked legacy - Update docs/architecture.md: remove "Browser / Cursor MCP", remove "Cursor-free" section headers, fix mcp/ package description - Update docs/guides/mcp.md: update transport table language, bump spec version ref to 2025-11-25, add HTTP security section (Origin + MCP-Protocol-Version requirements from previous PR) - Update docs/guides/integrate.md: remove "Cursor, Claude, and any MCP-compatible client" → "any MCP-compatible client" - Update docs/reference/mcp.md: bump protocol version, add HTTP endpoints table and security notes - stdio example config now says "e.g. Cursor" rather than implying Cursor is required; transport table updated for neutrality LLM-agnostic backend has been in place for months; these were leftover mentions from before that was true.
chore: remove Cursor domain bleed from code, comments, and docs
Implement the full elicitation protocol from MCP 2025-11-25, making
AgentCeption a best-in-class showcase for server-initiated human input
during live agent swarms.
## Backend
agentception/mcp/sessions.py (new)
- McpSession dataclass: session_id, elicitation_form/url flags,
asyncio outbound queue, pending Future dict
- McpSessionStore: create/get/delete/update_capabilities,
elicitation_sessions(mode), resolve_response
- Module-level singleton via get_store()
agentception/mcp/elicitation.py (new)
- _build_json_schema: converts ElicitationField list → MCP JSON Schema
- send_form_elicitation: puts elicitation/create in outbound queue,
awaits asyncio.Future with timeout
- request_human_input: MCP tool implementation — finds first form-capable
session, returns accept/decline/cancel/timeout/no_client actions
agentception/mcp/types.py
- ElicitationField, ElicitationResult — typed field spec and result
- ClientElicitationFormCapability, ClientElicitationUrlCapability,
ClientElicitationCapabilities, ClientCapabilities — initialize parsing
agentception/mcp/server.py
- request_human_input registered in TOOLS list (with full JSON Schema)
- call_tool_async: validates + dispatches request_human_input
- call_tool: adds request_human_input to async-redirect list
agentception/routes/api/mcp.py (rewritten)
- GET /api/mcp: SSE stream for sessions with Accept: text/event-stream
+ MCP-Session-Id; 405 without Accept; 403 on evil Origin; 400/404 on
bad session
- DELETE /api/mcp: terminates session, cancels pending futures
- POST /api/mcp on initialize: creates session, returns MCP-Session-Id
header, parses elicitation capabilities
- POST /api/mcp with JSON-RPC response (has id, no method): routes to
resolve_response → unblocks waiting request_human_input call
- SSE keepalive pings every 15s to prevent proxy timeouts
## Frontend
agentception/static/js/mcp_session.ts (new)
- initMcpSession: POST initialize with elicitation.form capability
- openSseStream: fetch-based SSE with exponential backoff reconnect
- sendMcpResponse: POST JSON-RPC response back to server
- terminateMcpSession: DELETE on pagehide
- registerMcpHandler: route server-initiated methods to handlers
agentception/static/js/elicitation_modal.ts (new)
- elicitationModal Alpine component: renders form from JSON Schema,
validates required fields, submits via sendMcpResponse
- dispatchElicitationEvent: window event bridge from SSE → Alpine
agentception/static/js/app.ts
- Imports mcp_session.ts and elicitation_modal.ts
- Registers elicitation/create handler → dispatches window event
- Calls initMcpSession() and registers terminateMcpSession on pagehide
agentception/templates/base.html
- Adds global elicitation modal HTML (present on every page)
- Uses Alpine elicitationModal() + @mcp:elicitation.window event
agentception/static/scss/_components.scss
- .elicitation-* styles: modal, form fields, labels, validation,
decline/submit buttons — matches existing design system
## Tests
agentception/tests/test_mcp_elicitation.py (new, 71 tests → 71 pass)
- McpSessionStore: CRUD, capability lookup, resolve_response
- _build_json_schema: all field types + constraints
- send_form_elicitation: round-trip, decline, timeout
- request_human_input: no_client, accept, timeout, JSON serialisation
agentception/tests/test_mcp_http.py
- TestMcpHttpSession: MCP-Session-Id header, elicitation capability
session creation, DELETE, RPC response routing
- TestMcpHttpTransportDisambiguation: renamed test to reflect that
GET with evil Origin → 403; added SSE tests (400, 404 cases)
- TestMcpHttpElicitationTool: tools/list includes request_human_input,
no_client path when store is empty
## Docs
docs/guides/mcp.md
- HTTP endpoint table (POST/GET/DELETE with purposes)
- "Elicitation — human-in-the-loop for running agents" section:
flow diagram, session lifecycle, tool usage, return values, when
to use it, no-client graceful degradation
mypy: 0 errors (309 files)
tsc: 0 errors
typing_audit: 0 violations (max-any 0)
71 tests, all pass
feat: MCP 2025-11-25 elicitation — human-in-the-loop for running agents
Completes the domain decoupling started in earlier PRs. Every instance of "Cursor" that implied the IDE was required or was the only way to work has been replaced with generic language (interactive session, agent session, server-side agent loop, MCP client, etc.). Changes by category: Source code: - code_indexer.py: docstring no longer frames as "Cursor-free" or "replaces @codebase" - task_runner.py: "(Cursor, Anthropic, etc.)" → "(Anthropic, local models, etc.)" - config.py: ".cursor/ which belongs to the IDE" → "IDE config directory" - smoke_test_agent_loop.py / debug_loop.py: remove "Cursor-free" from print/docstring - test_agentception_pipeline_config.py: rename cursor_dir → config_dir Templates: - overview.html: "open in Cursor" → "open the worktree" (two instances) Agent contracts: - AGENTS.md: "Cursor sessions" → "interactive development sessions" - .agentception/agent-engineer.md: "Cursor worktree/composer" → "git worktree/agent session" - .agentception/agent-conductor.md: "Cursor composer window" → "agent session" - .agentception/pipeline-howto.md: "Open two Cursor composer windows" → Task tool / agent sessions - .agentception/agent-command-policy.md: clarify section heading as "(Cursor as MCP client)" Generated role template: - scripts/gen_prompts/templates/roles/architect.md.j2: "Cursor/Claude tool integration" → "MCP client integration" - .agentception/roles/architect.md: regenerated Documentation: - docs/README.md: "Cursor-Free Agent Loop" → "AgentCeption Agent Loop"; generalize MCP section - README.md: "MCP Integration (Cursor / Claude)" → "MCP Integration" - docs/guides/agent-loop.md: rename guide, replace "What Cursor provided" table with "Built-In Capabilities" - docs/guides/security.md: generalize stdio section heading and "Cursor-free loop" references - docs/guides/setup.md: "Cursor-free agent loop" → "AgentCeption agent loop" (index section) - docs/guides/ci.md / dispatcher-walkthrough.md / mcp.md: keep Cursor as explicit "e.g." example - docs/architecture.md / cognitive-arch-audit.md / agent-tree-protocol.md: clean IDE refs - docs/reference/api.md: "Cursor-free dispatch" → "server-side dispatch"; "Cursor agent" → "planning agent" - docs/reference/type-contracts.md: "Cursor transcript", "CursorTaskRunner", "@codebase" references removed - docs/architecture/llm-provider-abstraction.md: "Cursor-free runs" → "server-side agent runs" - docs/plan-spec.md: "running in Cursor via MCP" → "running via MCP" - docs/plans/agent-speedup.md: "Cursor solves" → "IDE agents solve" Deleted: - docs/reference/cursor-decoupling-taxonomy.md: work-tracking doc for completed decoupling effort Kept intentionally: - .cursorrules (Cursor IDE config file) - docs/guides/dispatcher-walkthrough.md (Cursor-as-MCP-client example guide, already scoped) - docs/guides/setup.md Step 8/N (Cursor MCP setup, explicitly framed as "e.g. Cursor") - .agentception/agent-command-policy.md body (already prefixed with "When using Cursor as the MCP client") - CSS cursor: pointer, data cursors (api.md, sql.yaml), UI blinking cursor (thought_block.ts)
Remove IDE-specific Cursor references throughout the codebase
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
MCP-Protocol-Versionheader, session management,GET /api/mcpSSE stream,DELETE /api/mcpsession terminationrequest_human_inputtool,McpSessionStore,send_form_elicitation, SSE-backed frontend modal with Alpine.js, fullelicitation/createround-tripcursor-decoupling-taxonomy.md; renamed "Cursor-Free Agent Loop" → "AgentCeption Agent Loop" throughoutTest plan
mypy agentception/ tests/— zero errorstyping_audit.py --max-any 0— passespytest— all tests greennpx tsc --noEmit— zero errorsgenerate.py --check— no driftnpm run build— bundles built