gabriel / musehub public
feat patch mists task/phase5-mist-mcp-tools #1 / 1
gabriel · 163 days ago · Apr 15, 2026 · Diff

feat(mists): Phase 5 — MCP tools, read executors, and resource handlers

Add 7 MCP tools for the Mists domain, wired end-to-end through the tool catalogue, dispatcher, and resource URI router.

Write tools (musehub/mcp/write_tools/mists.py): muse_mist_create — publish content-addressed mist; auto-detects artifact_type, language, symbol_anchors muse_mist_update — partial update (title/description/visibility/tags/content); owner-only; content replacement increments version muse_mist_fork — fork into caller's namespace; enforces depth limit; source fork_count incremented atomically muse_mist_delete — hard-delete mist + backing repo via cascade; owner-only

Read executors (musehub/services/musehub_mcp_executor.py): execute_read_mist — fetch single mist; secret guard; increments view_count execute_list_mists — explore (owner=None) or per-owner; cursor pagination; artifact_type filter; secret include/exclude logic execute_read_mist_embed — iframe/JS/badge embed codes; increments embed_count; public-only

Tool definitions (musehub/mcp/tools/musehub.py): 3 tools added to MUSEHUB_READ_TOOLS (muse_mist_read, muse_mist_list, muse_mist_embed) 4 tools added to MUSEHUB_WRITE_TOOLS (muse_mist_create, muse_mist_update, muse_mist_fork, muse_mist_delete) Total tools: 111

Dispatcher routing (musehub/mcp/dispatcher.py): 7 new elif branches; write tools import lazily from write_tools/mists

Resource URI router (musehub/mcp/resources.py): Templates: musehub://mists/{owner}/{mist_id}, musehub://mists/{owner} Handlers: _read_mist, _read_owner_mists — secret guard; view_count increment

Tests (tests/test_mcp_mist_tools.py, 62 tests, all passing): Layer 1 Unit, Layer 2 Integration, Layer 3 E2E, Layer 4 Stress, Layer 5 Data Integrity, Layer 6 Security, Layer 7 Performance

sha256:865ae60faf0dd8984c1c77516564384b7bf614da993c67db3553d069cd76ba81 sha
+134 ~5 symbols
sha256:36fd74198a93b3343ea82e0d60f6c8c729164393aa7ede0777f14d0f9ca395bc snapshot
+134
symbols added
~5
symbols modified
0
dead code introduced
Semantic Changes 139 symbols
~ musehub/mcp/write_tools/mists.py .py 14 symbols added
+ _mist_data function function _mist_data L16–43
+ execute_create_mist function async_function execute_create_mist L46–180
+ execute_delete_mist function async_function execute_delete_mist L361–417
+ execute_fork_mist function async_function execute_fork_mist L262–358
+ execute_update_mist function async_function execute_update_mist L183–259
+ AsyncSessionLocal import import AsyncSessionLocal L10–10
+ JSONObject import import JSONObject L9–9
+ MusehubToolResult import import MusehubToolResult L11–11
+ _check_db_available import import _check_db_available L11–11
+ annotations import import annotations L3–3
+ logging import import logging L5–5
+ time import import time L6–6
+ uuid import import uuid L7–7
+ logger variable variable logger L13–13
~ tests/test_mcp_mist_tools.py .py 115 symbols added
+ TestDataIntegrity class class TestDataIntegrity L582–640
+ test_created_mist_in_owner_list method async_method test_created_mist_in_owner_list L591–597
+ test_created_mist_retrievable method async_method test_created_mist_retrievable L583–589
+ test_deleted_mist_not_found method async_method test_deleted_mist_not_found L607–614
+ test_embed_count_increments_on_embed method async_method test_embed_count_increments_on_embed L634–640
+ test_fork_parent_id_and_source_fork_count method async_method test_fork_parent_id_and_source_fork_count L616–625
+ test_update_title_persisted method async_method test_update_title_persisted L599–605
+ test_view_count_increments_on_read method async_method test_view_count_increments_on_read L627–632
+ TestE2EAuthGate class class TestE2EAuthGate L490–556
+ test_create_mist_no_auth method async_method test_create_mist_no_auth L493–499
+ test_create_mist_with_auth method async_method test_create_mist_with_auth L525–543
+ test_delete_mist_no_auth method async_method test_delete_mist_no_auth L517–523
+ test_fork_mist_no_auth method async_method test_fork_mist_no_auth L509–515
+ test_list_mists_read_tool_no_auth method async_method test_list_mists_read_tool_no_auth L545–556
+ test_update_mist_no_auth method async_method test_update_mist_no_auth L501–507
+ TestIntegrationCreate class class TestIntegrationCreate L240–282
+ test_create_duplicate_content_returns_already_exists method async_method test_create_duplicate_content_returns_already_exists L252–260
+ test_create_happy_path method async_method test_create_happy_path L241–250
+ test_create_secret_mist method async_method test_create_secret_mist L274–282
+ test_create_with_title_and_tags method async_method test_create_with_title_and_tags L262–272
+ TestIntegrationDelete class class TestIntegrationDelete L322–341
+ test_delete_happy_path method async_method test_delete_happy_path L323–329
+ test_delete_non_owner_returns_not_found method async_method test_delete_non_owner_returns_not_found L331–336
+ test_delete_unknown_returns_not_found method async_method test_delete_unknown_returns_not_found L338–341
+ TestIntegrationEmbed class class TestIntegrationEmbed L432–454
+ test_embed_public_mist method async_method test_embed_public_mist L433–442
+ test_embed_secret_mist_returns_forbidden method async_method test_embed_secret_mist_returns_forbidden L444–449
+ test_embed_unknown_mist_returns_not_found method async_method test_embed_unknown_mist_returns_not_found L451–454
+ TestIntegrationFork class class TestIntegrationFork L344–357
+ test_fork_happy_path method async_method test_fork_happy_path L345–352
+ test_fork_unknown_returns_not_found method async_method test_fork_unknown_returns_not_found L354–357
+ TestIntegrationListMists class class TestIntegrationListMists L390–429
+ test_explore_excludes_secret method async_method test_explore_excludes_secret L399–405
+ test_explore_returns_public method async_method test_explore_returns_public L391–397
+ test_owner_mode_excludes_secret_for_anon method async_method test_owner_mode_excludes_secret_for_anon L415–421
+ test_owner_mode_includes_public method async_method test_owner_mode_includes_public L407–413
+ test_owner_mode_includes_secret_for_owner method async_method test_owner_mode_includes_secret_for_owner L423–429
+ TestIntegrationReadMist class class TestIntegrationReadMist L360–387
+ test_read_public_mist_anon method async_method test_read_public_mist_anon L361–367
+ test_read_secret_mist_as_non_owner_returns_forbidden method async_method test_read_secret_mist_as_non_owner_returns_forbidden L375–382
+ test_read_secret_mist_as_owner method async_method test_read_secret_mist_as_owner L369–373
+ test_read_unknown_returns_not_found method async_method test_read_unknown_returns_not_found L384–387
+ TestIntegrationResource class class TestIntegrationResource L457–484
+ test_read_resource_owner_mists method async_method test_read_resource_owner_mists L466–472
+ test_read_resource_secret_mist_blocked_for_anon method async_method test_read_resource_secret_mist_blocked_for_anon L478–484
+ test_read_resource_single_mist method async_method test_read_resource_single_mist L458–464
+ test_read_resource_unknown_mist method async_method test_read_resource_unknown_mist L474–476
+ TestIntegrationUpdate class class TestIntegrationUpdate L285–319
+ test_update_content_increments_version method async_method test_update_content_increments_version L300–307
+ test_update_non_owner_returns_not_found method async_method test_update_non_owner_returns_not_found L309–314
+ test_update_title method async_method test_update_title L286–291
+ test_update_unknown_mist_returns_not_found method async_method test_update_unknown_mist_returns_not_found L316–319
+ test_update_visibility_to_secret method async_method test_update_visibility_to_secret L293–298
+ TestPerformance class class TestPerformance L703–760
+ test_10_creates_under_500ms method async_method test_10_creates_under_500ms L704–714
+ test_list_100_mists_under_200ms method async_method test_list_100_mists_under_200ms L716–760
+ TestSecurity class class TestSecurity L646–697
+ test_agent_id_stored_verbatim method async_method test_agent_id_stored_verbatim L687–697
+ test_content_returned_verbatim_no_xss_transform method async_method test_content_returned_verbatim_no_xss_transform L671–685
+ test_read_tools_not_in_write_set method method test_read_tools_not_in_write_set L652–655
+ test_secret_mist_blocked_for_non_owner_read method async_method test_secret_mist_blocked_for_non_owner_read L664–669
+ test_secret_mist_not_in_explore method async_method test_secret_mist_not_in_explore L657–662
+ test_write_tools_in_auth_gate_set method method test_write_tools_in_auth_gate_set L647–650
+ TestStressMistTools class class TestStressMistTools L562–576
+ test_10_sequential_creates method async_method test_10_sequential_creates L563–576
+ TestUnitInputValidation class class TestUnitInputValidation L205–234
+ test_create_empty_actor_returns_forbidden method async_method test_create_empty_actor_returns_forbidden L206–209
+ test_create_empty_content_returns_missing_args method async_method test_create_empty_content_returns_missing_args L216–219
+ test_create_empty_filename_returns_missing_args method async_method test_create_empty_filename_returns_missing_args L211–214
+ test_delete_empty_actor_returns_forbidden method async_method test_delete_empty_actor_returns_forbidden L231–234
+ test_fork_empty_actor_returns_forbidden method async_method test_fork_empty_actor_returns_forbidden L226–229
+ test_update_empty_actor_returns_forbidden method async_method test_update_empty_actor_returns_forbidden L221–224
+ TestUnitMistDataHelper class class TestUnitMistDataHelper L194–202
+ test_mist_data_keys method async_method test_mist_data_keys L195–202
+ TestUnitToolCatalogue class class TestUnitToolCatalogue L174–191
+ test_all_mist_tools_in_tool_names method method test_all_mist_tools_in_tool_names L185–191
+ test_mist_read_tools_NOT_in_write_set method method test_mist_read_tools_NOT_in_write_set L180–183
+ test_mist_write_tools_in_write_set method method test_mist_write_tools_in_write_set L175–178
+ _OWNER variable variable _OWNER L123–123
+ _PY_CONTENT variable variable _PY_CONTENT L124–124
+ _PY_FILENAME variable variable _PY_FILENAME L125–125
+ _create function async_function _create L155–168
+ _tools_call function function _tools_call L137–143
+ _uid function function _uid L128–129
+ _unique_content function function _unique_content L132–134
+ _unwrap_tool_text function function _unwrap_tool_text L146–152
+ anyio_backend function function anyio_backend L108–109
+ http_client function async_function http_client L113–118
+ ASGITransport import import ASGITransport L82–82
+ AsyncClient import import AsyncClient L82–82
+ AsyncSession import import AsyncSession L83–83
+ JSONObject import import JSONObject L88–88
+ MUSEHUB_TOOL_NAMES import import MUSEHUB_TOOL_NAMES L87–87
+ MUSEHUB_WRITE_TOOL_NAMES import import MUSEHUB_WRITE_TOOL_NAMES L87–87
+ StrDict import import StrDict L88–88
+ _mist_data import import _mist_data L89–89
+ annotations import import annotations L73–73
+ app import import app L86–86
+ datetime import import datetime L78–78
+ db import import db L85–85
+ execute_create_mist import import execute_create_mist L89–89
+ execute_delete_mist import import execute_delete_mist L89–89
+ execute_fork_mist import import execute_fork_mist L89–89
+ execute_list_mists import import execute_list_mists L96–96
+ execute_read_mist import import execute_read_mist L96–96
+ execute_read_mist_embed import import execute_read_mist_embed L96–96
+ execute_update_mist import import execute_update_mist L89–89
+ json import import json L75–75
+ pytest import import pytest L80–80
+ pytest_asyncio import import pytest_asyncio L81–81
+ read_resource import import read_resource L101–101
+ time import import time L76–76
+ timedelta import import timedelta L78–78
+ timezone import import timezone L78–78
+ uuid import import uuid L77–77
~ musehub/mcp/dispatcher.py .py 1 symbol modified
~ musehub/mcp/resources.py .py 2 symbols added, 2 symbols modified
+ _read_mist function async_function _read_mist L1063–1122
+ _read_owner_mists function async_function _read_owner_mists L1125–1174
+ execute_list_mists function async_function execute_list_mists L3533–3602
+ execute_read_mist function async_function execute_read_mist L3455–3530
+ execute_read_mist_embed function async_function execute_read_mist_embed L3605–3681
← Older Oldest on task/phase5-mist-mcp-tools
All commits
Newer → Latest on task/phase5-mist-mcp-tools

0 comments

No comments yet. Be the first to start the discussion.

To add a comment, use the Muse CLI: muse hub commit comment sha256:865ae60faf0dd8984c1c77516564384b7bf614da993c67db3553d069cd76ba81 --body "your comment"