feat: MCP capability negotiation + prompts support#5
Merged
Conversation
Mainly pillow, langchain-core and cryptography to solve security issue
Fix Dive#348: only call tools/list, prompts/list, etc. when the server
advertises the matching capability in its initialize response. Add a
defensive _safe_list helper that swallows -32601 Method not found so a
misbehaving server cannot break startup. Apply the same gating in
local_http_server's init path.
Add Dive#349: implement prompts/list and prompts/get on McpServer with
a cached list refreshed on notifications/prompts/list_changed.
Notifications are deduped via a tracked _refresh_prompts_task so bursts
do not stack up sessions. Expose prompts via McpServerInfo.prompts and
two new HTTP routes:
GET /api/tools/{server}/prompts
POST /api/tools/{server}/prompts/get
Tests cover tools-only, prompts-only, tools+prompts, and capabilities-
less servers, plus prompts/get round-trip, METHOD_NOT_FOUND fallback,
empty-cache reuse, and notification dedup.
README: full rewrite with badges, Mermaid architecture and lifecycle diagrams, Quick Start for HTTP / CLI / SDK, configuration walk-through, MCP capability and HTTP API tables. CLAUDE.md: project role and backwards-compat discipline, common commands, ContextProtocol-based lifecycle, McpServer transport dispatch and capability gating, persistence layout, testing notes.
- add docstrings to build_server / main in capability_server.py - wrap build_server signature to fit 88-col line length - mark unused `name` arg in _call_tool with noqa ARG001 - reformat patch.object call in test for line length
- README: corrected DiveMcpHost import path (dive_mcp_host.host.host,
not dive_mcp_host.host — the latter's __init__.py is empty, so the
quick-start snippet as written would ImportError).
- Wrap new prompts HTTP endpoints in the repo-standard DataResult[T]
envelope to match skills.py and the rest of the API surface, so
frontends always see {success, message, data}. Drops the bespoke
GetPromptResponse model in favour of DataResult[GetPromptResult].
- Apply `ruff format` to the files missed in the earlier style pass
(mcp_server.py, tests/mcp_servers/capability_server.py,
tests/test_capabilities_and_prompts.py).
- mcp_server.py:1109 was assigning to `self._init_result`, a typo — the rest of the class reads `self._initialize_result`. Local-HTTP spawn-and-connect servers therefore always reported initialize_result=None, and my _supports_prompts() helper couldn't tell whether they advertised prompts. Fixed the attribute name. - test_stream_logs_notfound_wait / test_stream_logs_name_with_slash were pinned to responses[-3] == STREAMING_ERROR. Adding prompts/list during init made the fastmcp-based echo server emit one more "Processing request of type ListPromptsRequest" stderr line, shifting the index to [-4]. Rewrote the assertions to check the invariant (one or more STREAMING_ERROR followed by STDERR+INIT events, ending in STATUS_CHANGE+RUNNING) without hard-coding event counts. - Added a regression test that asserts local-HTTP servers now populate initialize_result.
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
tools/list/prompts/listare only called when the server advertises the matching capability. A defensive_safe_listhelper swallows-32601 Method not foundso a misbehaving server cannot break startup. Same gating applied to the local-HTTP init path.prompts/list,prompts/getround-trip, and auto-refresh onnotifications/prompts/list_changed(notifications deduped via a tracked task so bursts don't stack up sessions).New HTTP endpoints (the existing
/api/toolsresponse also carriesprompts):Backwards compatibility
Wire format changes are purely additive:
McpTool/McpServerInfogainprompts: [...] = [](Pydantic v2 defaultextra="ignore")./initialized,/login/oauth/*,/elicitation/respond) are registered before the new path-param route, so FastAPI matches them first.McpServer/ToolManager/DiveMcpHostwas renamed or removed.Behavior change: servers that previously failed init because they advertised tools but returned -32601 on
tools/list(or were prompts-only) now come up asRUNNINGwith the correct partial inventory. Old front-ends see this as "more servers work now" rather than a regression.Docs:
README.mdrewritten with badges, Mermaid architecture + lifecycle diagrams, config walk-through, capability table.CLAUDE.mdadded.Test plan
pytest tests/test_capabilities_and_prompts.py— 12/12 pass: tools-only, prompts-only, tools+prompts, no-capabilities, METHOD_NOT_FOUND fallback (both live server and unit), prompt round-trip, list-changed refresh, cache-no-refetch on empty,get_promptwithout capability raisesValueError, notification dedup.pytest tests/test_tools.py tests/httpd/routers/test_tools.py— no regressions in existing suites (53 pass; 3 pre-existing environmental failures unrelated to these changes:test_tool_proxy,test_stream_logs_*).#349UI (separate PR in main Dive repo).