Skip to content

Commit 7ca8bb5

Browse files
refactor: consolidate tool retirement logic into a dedicated module and clean up legacy registration code (#112)
1 parent 7a1c71b commit 7ca8bb5

21 files changed

Lines changed: 266 additions & 213 deletions

agent-docs/agents/prompts/README.md

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22

33
MCP Prompt Markdown is bundled with the server under
44
`src/fls_pilot/context/prompts/`. That package directory is the canonical
5-
runtime source used by `src/fls_pilot/prompts.py`.
5+
runtime source used by `src/fls_pilot/prompts.py`. Only runtime prompts are
6+
registered as public MCP prompts.
67

78
## Three Layers: Prompts · Resources · Tools
89

@@ -30,15 +31,6 @@ runtime source used by `src/fls_pilot/prompts.py`.
3031
| `composition_scale_writer` | `src/fls_pilot/context/prompts/composition-scale-writer.md` | Raga/scale melody and chord composition |
3132
| `audio_to_midi_or_reference_analysis` | `src/fls_pilot/context/prompts/audio-to-midi.md` | Audio analysis and optional MIDI extraction |
3233

33-
### Dev Prompts (Developer / Agent Tooling)
34-
35-
| Prompt name | Source file | Purpose |
36-
|-------------|------|---------|
37-
| `api_probe` | `src/fls_pilot/context/prompts/api-probe.md` | Safe FL API compatibility probe |
38-
| `bug_triage` | `src/fls_pilot/context/prompts/bug-triage.md` | GitHub bug classification and prep |
39-
| `implementation_slice` | `src/fls_pilot/context/prompts/implementation-slice.md` | Narrow pre-approved dev slice execution |
40-
| `release_prepare` | `src/fls_pilot/context/prompts/release.md` | Release checks, tagging, validation |
41-
4234
## Using Prompts via MCP
4335

4436
MCP clients that support prompts can invoke them by name:

agent-docs/concepts/api-capability-audit.md

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -132,19 +132,20 @@ Not currently supported:
132132

133133
The current baseline, regenerated on 2026-06-14, reports:
134134

135-
- 94 registered public FastMCP tools with 94 unique public names after v2.0
136-
legacy low-level alias removal.
135+
- 91 registered public FastMCP tools with 91 unique public names after runtime-only
136+
MCP cleanup.
137137
- 167 statically audited tool definitions.
138138
- 33 registered `write-safe-required` tools.
139139
- 0 `write-gap` tools.
140140
- 0 `needs-review` tools.
141-
- 41 registered `read-only` tools.
141+
- 50 registered `read-only` tools.
142142
- 4 `server-state` tools.
143143
- 2 `external-write` tools.
144144
- 1 registered `transient` domain tool and 6 statically audited transient
145145
legacy/helper tools.
146-
- 13 registered tools are not covered by the static AST audit because they are
147-
registered via direct `mcp.tool()(fn)` calls without safety annotations.
146+
- 1 registered public tool remains unannotated.
147+
- 10 registered tools are not covered by the static AST audit because they are
148+
registered via direct `mcp.tool(...)(fn)` calls.
148149
- 86 statically audited legacy low-level tool definitions remain in source for
149150
helper/test compatibility but are intentionally absent from public
150151
registration.

docs/mcp-integration.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,7 @@ Runtime agents should start with MCP context, not repository file reads:
1919

2020
MCP prompts are available for guided workflows such as Mix Review, Routing
2121
Review, Project Organizer, Project Preflight, Plugin Chain Planning,
22-
Composition, Audio Analysis, API probes, bug triage, implementation slices, and
23-
release preparation.
22+
Composition, and Audio Analysis.
2423

2524
## Domain Tools
2625

pyproject.toml

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,55 @@ Repository = "https://github.com/thunderdew-dawn/fls-pilot"
8080
Issues = "https://github.com/thunderdew-dawn/fls-pilot/issues"
8181
Upstream = "https://github.com/rosasynthesiz/flstudio-mcp"
8282

83+
[tool.hatch.build]
84+
include = [
85+
"/src/fls_pilot/**/*.py",
86+
"/src/fls_pilot/context/**/*.md",
87+
"/src/fls_pilot/context/**/*.json",
88+
"/src/fls_pilot/context/**/*.yaml",
89+
"/src/fls_pilot/context/**/*.yml",
90+
"/knowledgebase/**/*.md",
91+
"/knowledgebase/**/*.json",
92+
"/knowledgebase/**/*.yaml",
93+
"/knowledgebase/**/*.yml",
94+
"/docs/**/*.md",
95+
"/README.md",
96+
"/LICENSE",
97+
]
98+
exclude = [
99+
"/.github/**",
100+
"/.gitignore",
101+
"/.pytest_cache/**",
102+
"/.ruff_cache/**",
103+
"/agent-docs/**",
104+
"/dist/**",
105+
"/docs/community/**",
106+
"/docs/requirements.txt",
107+
"/knowledgebase/agent_notes/**",
108+
"/scratch/**",
109+
"/scripts/calibration/**",
110+
"/scripts/probes/**",
111+
"/tests/**",
112+
"/src/fls_pilot/context/prompts/api-probe.md",
113+
"/src/fls_pilot/context/prompts/bug-triage.md",
114+
"/src/fls_pilot/context/prompts/implementation-slice.md",
115+
"/src/fls_pilot/context/prompts/release.md",
116+
"**/__pycache__/**",
117+
]
118+
83119
[tool.hatch.build.targets.wheel]
84120
packages = ["src/fls_pilot"]
85-
artifacts = ["src/fls_pilot/context/**/*.md"]
121+
force-include = { "knowledgebase" = "knowledgebase" }
122+
123+
[tool.hatch.build.targets.sdist]
124+
only-include = [
125+
"src",
126+
"knowledgebase",
127+
"docs",
128+
"README.md",
129+
"LICENSE",
130+
"pyproject.toml",
131+
]
86132

87133
[tool.ruff]
88134
line-length = 100

scripts/check_tool_registration_baseline.py

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,16 @@
1919

2020
from fls_pilot import __version__ # noqa: E402
2121
from fls_pilot import server as server_module # noqa: E402
22+
from fls_pilot.tools.registration import RETIRED_LOW_LEVEL_TOOLS # noqa: E402
2223

23-
EXPECTED_REGISTERED_TOOL_COUNT = 94
24+
EXPECTED_REGISTERED_TOOL_COUNT = 91
2425
EXPECTED_STATIC_TOOL_COUNT = 167
2526
EXPECTED_REGISTERED_SAFETY_SUMMARY = {
2627
"external-write": 2,
27-
"read-only": 41,
28+
"read-only": 50,
2829
"server-state": 4,
2930
"transient": 1,
30-
"unannotated": 13,
31+
"unannotated": 1,
3132
"write-safe-required": 33,
3233
}
3334
EXPECTED_STATIC_SAFETY_SUMMARY = {
@@ -152,9 +153,7 @@ def main() -> int:
152153
static_summary = {"write-gap": 0, **count_by_status(static_audits)}
153154
registered_not_static = sorted(registered_name_set - static_names)
154155
static_not_registered = sorted(static_names - registered_name_set)
155-
expected_static_not_registered = sorted(
156-
getattr(server_module, "_LEGACY_LOW_LEVEL_TOOLS", set()) & static_names
157-
)
156+
expected_static_not_registered = sorted(RETIRED_LOW_LEVEL_TOOLS & static_names)
158157

159158
print("Tool registration baseline")
160159
print(f"- registered_public_tools: {len(registered_tools)}")

src/fls_pilot/context/docs/api-capability-audit.md

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -132,19 +132,20 @@ Not currently supported:
132132

133133
The current baseline, regenerated on 2026-06-14, reports:
134134

135-
- 94 registered public FastMCP tools with 94 unique public names after v2.0
136-
legacy low-level alias removal.
135+
- 91 registered public FastMCP tools with 91 unique public names after runtime-only
136+
MCP cleanup.
137137
- 167 statically audited tool definitions.
138138
- 33 registered `write-safe-required` tools.
139139
- 0 `write-gap` tools.
140140
- 0 `needs-review` tools.
141-
- 41 registered `read-only` tools.
141+
- 50 registered `read-only` tools.
142142
- 4 `server-state` tools.
143143
- 2 `external-write` tools.
144144
- 1 registered `transient` domain tool and 6 statically audited transient
145145
legacy/helper tools.
146-
- 13 registered tools are not covered by the static AST audit because they are
147-
registered via direct `mcp.tool()(fn)` calls without safety annotations.
146+
- 1 registered public tool remains unannotated.
147+
- 10 registered tools are not covered by the static AST audit because they are
148+
registered via direct `mcp.tool(...)(fn)` calls.
148149
- 86 statically audited legacy low-level tool definitions remain in source for
149150
helper/test compatibility but are intentionally absent from public
150151
registration.

src/fls_pilot/context/prompts/README.md

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# MCP Prompts — Agent Guide
22

3-
This directory contains the canonical Markdown content for all MCP Prompts
3+
This directory contains the canonical Markdown content for runtime MCP Prompts
44
registered by the FLStudioPilot server.
55

66
## Three Layers: Prompts · Resources · Tools
@@ -29,15 +29,6 @@ registered by the FLStudioPilot server.
2929
| `composition_scale_writer` | `composition-scale-writer.md` | Raga/scale melody and chord composition |
3030
| `audio_to_midi_or_reference_analysis` | `audio-to-midi.md` | Audio analysis and optional MIDI extraction |
3131

32-
### Dev Prompts (Developer / Agent Tooling)
33-
34-
| Prompt name | File | Purpose |
35-
|-------------|------|---------|
36-
| `api_probe` | `api-probe.md` | Safe FL API compatibility probe |
37-
| `bug_triage` | `bug-triage.md` | GitHub bug classification and prep |
38-
| `implementation_slice` | `implementation-slice.md` | Narrow pre-approved dev slice execution |
39-
| `release_prepare` | `release.md` | Release checks, tagging, validation |
40-
4132
## Using Prompts via MCP
4233

4334
MCP clients that support prompts can invoke them by name:

src/fls_pilot/prompts.py

Lines changed: 0 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,6 @@
1515
mix_review, routing_review, project_organizer, project_preflight,
1616
plugin_chain_planner, composition_scale_writer,
1717
audio_to_midi_or_reference_analysis
18-
19-
Dev prompts (developer / agent tooling):
20-
api_probe, bug_triage, implementation_slice, release_prepare
2118
"""
2219

2320
from __future__ import annotations
@@ -126,31 +123,6 @@ def _workflow_preamble(workflow_key: str) -> str:
126123
"audio_analysis",
127124
"Analyze an audio file for tempo/key/melody; optionally write MIDI to Piano Roll.",
128125
),
129-
# Dev prompts
130-
(
131-
"api_probe",
132-
"api-probe.md",
133-
None,
134-
"Plan a safe API/compatibility probe for an undocumented FL Studio behavior.",
135-
),
136-
(
137-
"bug_triage",
138-
"bug-triage.md",
139-
None,
140-
"Classify and prepare a GitHub bug report before implementation.",
141-
),
142-
(
143-
"implementation_slice",
144-
"implementation-slice.md",
145-
None,
146-
"Claim and execute a narrow pre-approved development slice.",
147-
),
148-
(
149-
"release_prepare",
150-
"release.md",
151-
None,
152-
"Prepare a release: checks, tagging, dist validation, rollback plan.",
153-
),
154126
]
155127

156128

src/fls_pilot/server.py

Lines changed: 1 addition & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
from fastmcp import FastMCP
2424

2525
from . import __version__
26+
from . import prompts as prompt_defs
2627
from .connection import list_ports
2728
from .protocol import port_from_fl_name, port_to_fl_name
2829
from .runtime_config import DEFAULT_SSE_HOST, DEFAULT_SSE_PORT
@@ -36,15 +37,13 @@
3637
from .tools import color as color_tools
3738
from .tools import compose as compose_tools
3839
from .tools import effect as effect_domain_tools
39-
from .tools import effects as effects_tools
4040
from .tools import export as export_tools
4141
from .tools import knowledgebase as knowledgebase_tools
4242
from .tools import mix_doctor as mix_doctor_tools
4343
from .tools import mixer as mixer_tools
4444
from .tools import mixer_core as mixer_core_tools
4545
from .tools import mixing as mixing_tools
4646
from .tools import pattern as pattern_domain_tools
47-
from .tools import patterns_playlist as patterns_playlist_tools
4847
from .tools import pianoroll as pianoroll_tools
4948
from .tools import playlist as playlist_domain_tools
5049
from .tools import plugin as plugin_tools
@@ -56,107 +55,9 @@
5655
from .tools import routing as routing_tools
5756
from .tools import transport as transport_tools
5857
from .tools import workflow_context as workflow_context_tools
59-
from . import prompts as prompt_defs
6058

6159
logger = logging.getLogger("fls_pilot")
6260

63-
_LEGACY_LOW_LEVEL_TOOLS = {
64-
# Transport one-off aliases. Use fl_transport(action, params).
65-
"fl_ping",
66-
"fl_get_tempo",
67-
"fl_set_tempo",
68-
"fl_play",
69-
"fl_stop",
70-
"fl_toggle_play",
71-
"fl_record",
72-
"fl_get_play_state",
73-
"fl_get_song_position",
74-
"fl_set_song_position",
75-
"fl_get_time_signature",
76-
"fl_set_time_signature",
77-
# Mixer/channel core aliases. Use fl_mixer/fl_channel or retained safety tools.
78-
"fl_get_mixer_state",
79-
"fl_get_channel_state",
80-
"fl_set_mixer_volume",
81-
"fl_set_mixer_pan",
82-
"fl_set_mixer_mute",
83-
"fl_set_mixer_solo",
84-
"fl_set_mixer_name",
85-
"fl_set_channel_volume",
86-
"fl_set_channel_pan",
87-
"fl_set_channel_mute",
88-
"fl_set_channel_solo",
89-
"fl_mixer_list_tracks",
90-
"fl_mixer_get_track",
91-
"fl_mixer_set_volume",
92-
"fl_mixer_set_pan",
93-
"fl_mixer_set_mute",
94-
"fl_mixer_set_solo",
95-
"fl_mixer_select_track",
96-
"fl_mixer_get_route",
97-
"fl_mixer_set_route",
98-
"fl_mixer_set_stereo_separation",
99-
# Channel organizer aliases that are covered by fl_channel.
100-
"fl_get_channel_details",
101-
"fl_set_channel_name",
102-
"fl_set_channel_mixer_track",
103-
"fl_channel_get_grid",
104-
"fl_channel_set_grid_bit",
105-
"fl_channel_set_step_param",
106-
"fl_channel_set_steps",
107-
"fl_channel_clear_grid",
108-
"fl_classify_channels",
109-
# Routing one-off aliases covered by fl_mixer route actions.
110-
"fl_get_routing",
111-
"fl_set_route",
112-
# Pattern and playlist one-off aliases. Use fl_pattern/fl_playlist.
113-
"fl_pattern_list",
114-
"fl_pattern_get",
115-
"fl_pattern_get_length",
116-
"fl_pattern_select",
117-
"fl_pattern_rename",
118-
"fl_pattern_set_color",
119-
"fl_pattern_set_length",
120-
"fl_pattern_find_empty",
121-
"fl_playlist_list_tracks",
122-
"fl_playlist_get_track",
123-
"fl_playlist_set_mute",
124-
"fl_playlist_set_solo",
125-
"fl_playlist_set_name",
126-
"fl_playlist_set_color",
127-
"fl_playlist_select_track",
128-
# Effect slot and native EQ one-off aliases. Use fl_effect.
129-
"fl_effect_get_slot",
130-
"fl_effect_list_slots",
131-
"fl_effect_set_slot_mix",
132-
"fl_effect_get_track_slots_enabled",
133-
"fl_effect_set_track_slots_enabled",
134-
"fl_effect_set_slot_enabled",
135-
"fl_eq_get",
136-
"fl_eq_set_band",
137-
# Already-loaded plugin parameter aliases. Use fl_plugin.
138-
"fl_plugin_list",
139-
"fl_plugin_get_params",
140-
"fl_plugin_set_param",
141-
"fl_plugin_list_params",
142-
"fl_plugin_get_param",
143-
# Piano Roll one-off aliases. Use fl_piano_roll.
144-
"fl_write_piano_roll_notes",
145-
"fl_quantize_pattern",
146-
"fl_piano_write_notes",
147-
"fl_piano_write_chord",
148-
"fl_piano_clear",
149-
"fl_piano_quantize",
150-
"fl_piano_transpose",
151-
"fl_piano_duplicate",
152-
"fl_piano_velocity_ramp",
153-
"fl_piano_probe_return_channel",
154-
"fl_piano_add_marker",
155-
"fl_piano_add_time_signature_marker",
156-
"fl_piano_clear_markers",
157-
"fl_piano_get_notes",
158-
}
159-
16061

16162
SERVER_INSTRUCTIONS = """\
16263
FL Studio Pilot server -- control FL Studio from an AI assistant.
@@ -219,7 +120,6 @@ def build_server() -> FastMCP:
219120
channel_tools.register(mcp) # Channel organizer: details, names, mixer assignment
220121
pianoroll_tools.register(mcp) # Phase 2: write notes into the piano roll
221122
plugin_tools.register(mcp) # Phase 1B: plugin param read/write (name or index)
222-
effects_tools.register(mcp) # Effect slot + native EQ pack
223123
mixing_tools.register(mcp) # Slice B: high-level EQ mixing intents
224124
routing_tools.register(mcp) # Routing/cleanup Slice 1: read-only
225125
bulk_tools.register(mcp) # Bulk mute/solo: server-side group orchestration
@@ -234,12 +134,9 @@ def build_server() -> FastMCP:
234134
export_tools.register(mcp) # MIDI export: arrangement spec -> type-1 .mid on disk
235135
presets_tools.register(mcp) # Preset suggester: read preset names from disk
236136
mix_doctor_tools.register(mcp) # Mix Review: diagnose whole mix + gated adjustments
237-
patterns_playlist_tools.register(mcp) # Phase 3: Patterns & Playlist pack
238137
knowledgebase_tools.register(mcp) # KB Tools
239138
workflow_context_tools.register(mcp) # Workflow context: read-only fl_get_workflow_context
240139
prompt_defs.register(mcp) # MCP Prompts: guided workflow templates
241-
for name in sorted(_LEGACY_LOW_LEVEL_TOOLS):
242-
mcp.local_provider.remove_tool(name)
243140
return mcp
244141

245142

0 commit comments

Comments
 (0)