Skip to content

Fix feature import from expand chat: pin mcp<2 and report MCP-created features - #273

Open
zwanski-start wants to merge 3 commits into
AutoForgeAI:masterfrom
zwanski-start:swarm/issue-72-dennis
Open

zwanski-start wants to merge 3 commits into
AutoForgeAI:masterfrom
zwanski-start:swarm/issue-72-dennis

Conversation

@zwanski-start

Copy link
Copy Markdown

Closes #72

Root cause

The model wasn't making a bad call — it had nothing to call. When feature creation through MCP fails, the model invents a fallback, like npx claude-spec feature_import .... That package doesn't exist, which is why npm returns a 404. This PR covers three issues:

  1. The feature MCP server can't start on fresh installs. mcp is only a transitive dependency of claude-agent-sdk (mcp>=1.19.0, no upper bound), so new installs now resolve mcp 2.x. mcp 2.x removed mcp.server.fastmcp.FastMCP, so mcp_server/feature_mcp.py crashes on import with ModuleNotFoundError: No module named 'mcp.server.fastmcp', and no feature_* tools are available to any session (expand chat, initializer, or coding agent). I hit this myself in a freshly built venv (mcp 2.3.0). Fix: pin mcp>=1.19.0,<2.0.0 in requirements.txt and requirements-prod.txt. Because requirements-prod.txt changed, the npm CLI's requirements-hash marker also changes, so existing ~/.autoforge/venv installs reinstall and pick up the pin.
  2. The expand chat never reported created features. The session was switched to creating features through MCP in 3161c12, after this issue was filed, but nothing ever emitted the features_created WebSocket event. As a result, the chat showed no "Created N features" confirmation, featuresCreated stayed at 0, and ExpandProjectModal never called onFeaturesAdded(), so the kanban board didn't refresh. Even successful imports looked like failures. Fix: ExpandChatSession._query_claude now tracks feature_create / feature_create_bulk tool calls and their results, and emits features_created with the new IDs, names and categories. feature_create_bulk now also returns feature_ids. This only adds a key, so existing callers are unaffected.
  3. The prompt allowed made-up workarounds. expand-project.md now says the MCP tools are the only way to import features. It tells the model never to suggest CLI or npm commands, never to write a JSON file as a workaround, and to quote the tool's error back to the user instead.

Verification

  • New test_expand_chat_session.py (6 tests): result parsing for bulk and single creation, error and garbage results, and a streamed tool-use → tool-result sequence emitting features_created. Failed or unrelated tool calls are ignored.
  • I started the real python -m mcp_server.feature_mcp over stdio with mcp 1.30.0, called feature_create_bulk, and fed its actual result into the parser. It returned the correct IDs, names and categories.
  • ruff check ., python test_security.py, pytest test_client.py test_dependency_resolver.py all pass. mypy reports only pre-existing errors.

Not verified / assumptions

  • I did not run a live expand chat against the Claude API. The UI code is unchanged; it already handled features_created.
  • I pinned mcp<2 rather than porting feature_mcp.py to the mcp 2.x MCPServer API. Porting is a larger change and can be done as a follow-up.

🤖 Generated with Claude Code

zwanski-start and others added 3 commits October 22, 2026 07:09
)

mcp is only a transitive dependency of claude-agent-sdk, so fresh installs
now resolve mcp 2.x, where FastMCP was removed. feature_mcp.py then fails
on import, the features MCP server never starts, and chat sessions cannot
create features (the model falls back to inventing CLI commands).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The expand session never emitted features_created after switching to MCP
feature creation, so the chat showed no confirmation, the session count
stayed at 0, and the kanban board was never refreshed on close.

Track feature_create/feature_create_bulk tool calls and their results and
emit features_created with the new IDs. feature_create_bulk now also
returns feature_ids.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@zwanski-start

Copy link
Copy Markdown
Author

🔍 QA report: ✅ Passed

Tester: Barbara (cubefarm agent, in a fresh session) · Round: 1 · Author: Dennis

Confirmed the root cause: a fresh install from master resolves mcp 2.3.0, and in that venv feature_mcp.py fails on import (No module named 'mcp.server.fastmcp'). With the PR's mcp<2 pin both requirements files resolve mcp 1.30.0. The new features_created reporting works against the real feature MCP server over stdio (correct IDs, names and categories, including Unicode), and in the browser, with the expand WebSocket mocked, the UI shows 'Created 2 new features!' and the '2 added' counter. ruff, mypy (no new errors), 61 pytest tests (6 new), both security suites, the UI build and lint all pass; the prompt change was not tested against a live Claude API.

Check Details
✅ Root cause reproduced (mcp 2.x breaks feature MCP) uv pip compile of master requirements-prod.txt resolves mcp==2.3.0. In a fresh venv with it, import mcp_server.feature_mcp raises ModuleNotFoundError: No module named 'mcp.server.fastmcp'.
✅ Pin resolves mcp 1.x With the PR, both requirements.txt and requirements-prod.txt resolve mcp==1.30.0.
✅ Real MCP server round-trip feeds the parser Ran feature_mcp over stdio (19 tools). feature_create_bulk returned {created:3, with_dependencies:1, feature_ids:[1,2,3]} and parse_created_features matched IDs to input names and categories, including Unicode/em-dash names. feature_create (single) parsed to id 4. Features appear in GET /api/projects/qa-demo/features and on the Kanban board.
✅ features_created forwarded to UI The expand_project.py router passes session chunks straight to the browser. With the expand WebSocket mocked in Playwright (emitting the backend's payload shape, no API call), the chat shows the 'Created 2 new features!' system message and the '2 added' header counter.
✅ Failed/unrelated tool results ignored Covered by test_query_ignores_failed_and_unrelated_tools: an is_error result and a non-feature tool are ignored. Error and garbage JSON results return [] (test_parse_errors_and_garbage).
✅ Backward compatibility of feature_create_bulk result Only adds a feature_ids key; created and with_dependencies are unchanged. No schema changes.
⏭️ Prompt forbids invented import commands Reviewed the expand-project.md addition; it is reasonable. Model behaviour was not tested because that needs a live Claude API run.
✅ Server boot, REST and /ws uvicorn on 127.0.0.1:5443 with an isolated HOME: / 200, GET /api/projects 200, POST project 200, invalid name 422, /ws/projects/qa-demo streams agent_status.
✅ Responsive layout and console Expand chat renders correctly at 390x844. No console errors or warnings.
✅ Security / process cleanup security.py and the localhost middleware are untouched. No orphan feature_mcp or uvicorn processes after shutdown, and no secrets are logged.
⏭️ UI Playwright e2e suite The PR does not touch UI code.
🧪 Commands run
Command Result
uv pip compile requirements-prod.txt (master vs PR) master: mcp==2.3.0; PR: mcp==1.30.0 (also requirements.txt)
fresh venv with master deps: python -c 'import mcp_server.feature_mcp' ModuleNotFoundError: No module named 'mcp.server.fastmcp' (bug reproduced)
ruff check . All checks passed
mypy . (PR vs origin/master worktree) no new errors; the one extra is from the local venv/ directory
pytest test_expand_chat_session.py test_client.py test_dependency_resolver.py test_rate_limit_utils.py 61 passed, 0 failed
python test_security.py ALL TESTS PASSED
python test_security_integration.py ALL INTEGRATION TESTS PASSED
stdio MCP probe script (feature_create_bulk / feature_create -> parse_created_features) correct ids/names/categories
npm --prefix ui run build success
npm --prefix ui run lint 0 errors, 6 warnings (none in files this PR touches)
uvicorn server.main:app --port 5443 + curl REST + websockets /ws 200/200/200/422, ws streams agent_status

No browser screenshots were taken in this round.

Posted by cubefarm · merges automatically once GitHub's checks pass

cabana8471-arch pushed a commit to cabana8471-arch/autoforge that referenced this pull request Nov 7, 2026
Partial integration: takes parse_created_features, the tool-result loop in expand_chat_session.py (features_created is now incremented and emitted to the UI), feature_ids in feature_create_bulk, the expand-project.md failure guidance and test_expand_chat_session.py. Drops the PR's requirements*.txt hunks (my-features already pins mcp<2). Adds a test that feature_create_bulk returns the created IDs in input order.

Integrates AutoForgeAI#273

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AeH26pcsqoxPb3CDs8g1VN
cabana8471-arch added a commit to cabana8471-arch/autoforge that referenced this pull request Nov 7, 2026
In a real Expand chat the feature_create_bulk result arrives as {"result": "{\"created\": 2, ...}"}: FastMCP wraps a tool's string return value. parse_created_features (AutoForgeAI#273) looked for 'created' at the top level, logged 'created no features' and emitted no features_created event, so the UI never showed 'Created N new features'. The PR's tests only used unwrapped payloads.

The wrapper is now unwrapped before parsing. Verified in the browser: an Expand chat that creates a feature shows 'Created 1 new feature!' and the '1 added' badge.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AeH26pcsqoxPb3CDs8g1VN
cabana8471-arch pushed a commit to cabana8471-arch/autoforge that referenced this pull request Nov 8, 2026
…Project chat

Adaptations: EXPAND_TOOLS_PROMPT goes into the --system-prompt-file prompt together with my-features' NO_SHELL_PROMPT_NOTE; the PR's tests are merged into the existing test_expand_chat_session.py (from AutoForgeAI#273) and read the prompt from the file and stub find_claude_cli.

Integrates AutoForgeAI#270

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AeH26pcsqoxPb3CDs8g1VN
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug: feature import does not work

1 participant