Okay, let's break down prompt_library.py
into a more modular structure within the promptlib
directory.
The core idea is to separate concerns:
- Data Structures (Types): Definitions of how cursor rules look.
- Constants: Configuration like paths and patterns.
- Core Rule Logic: Functions for reading, parsing, and generating rule files.
- MCP Endpoints: Separate files for Resources, Prompts, and Tools.
- Complex Workflows: Isolate the multi-phase workflow logic.
- Server Setup: Initialize the FastMCP server and register all endpoints.
Here's a simplified, modular structure within src/codegen_lab/promptlib
:
src/codegen_lab
├── __init__.py
├── __main__.py
├── __version__.py
├── cli.py
└── promptlib # <--- All new logic goes here
├── __init__.py
├── constants.py # <--- CURSOR_RULES_DIR, TECHNOLOGY_PATTERNS
├── types.py # <--- TypedDict definitions (CursorRule, etc.)
├── rules.py # <--- Core rule file handling (read, parse, generate)
├── resources.py # <--- @mcp.resource functions
├── prompts.py # <--- @mcp.prompt functions
├── tools.py # <--- Most @mcp.tool functions
├── workflow.py # <--- plan_and_execute_... workflow tool + helpers
└── server.py # <--- FastMCP instance creation & registration of all endpoints
Explanation:
constants.py
: HoldsCURSOR_RULES_DIR
andTECHNOLOGY_PATTERNS
.types.py
: Contains all theTypedDict
definitions (CursorRuleMetadata
,CursorRule
, etc.).rules.py
: Houses the functions that directly interact with rule files:get_cursor_rule_files
,get_cursor_rule_names
,read_cursor_rule
,parse_cursor_rule
,generate_cursor_rule
.resources.py
: Contains the functions decorated with@mcp.resource
(list_cursor_rules
,get_cursor_rule
,get_cursor_rule_raw
).prompts.py
: Contains the functions decorated with@mcp.prompt
(repo_analysis_prompt
,generate_cursor_rule_prompt
).tools.py
: Contains most functions decorated with@mcp.tool
(e.g.,instruct_repo_analysis
,get_static_cursor_rule
,save_cursor_rule
,prep_workspace
, etc.).workflow.py
: Specifically isolates the complexplan_and_execute_prompt_library_workflow
tool and its helper functions (execute_phase_1
toexecute_phase_5
). This keeps the most complex logic separate.server.py
:- Initializes the
FastMCP
instance (mcp = FastMCP(...)
). - Imports the functions from
resources.py
,prompts.py
,tools.py
, andworkflow.py
. - Crucially, it applies the
@mcp.resource
,@mcp.prompt
, and@mcp.tool
decorators here to register the imported functions with themcp
instance. This avoids circular dependencies. - Defines a function like
run_server()
which callsmcp.run()
.
- Initializes the
prompt_library.py
: This original file can now be deleted or significantly reduced. Its responsibilities are moved into thepromptlib
modules.__main__.py
: This file should now importrun_server
frompromptlib.server
and call it in itsif __name__ == "__main__":
block to start the server.
Here's what should be moved from the original prompt_library.py
to the new modules:
1. Move to promptlib/constants.py
:
* [ ] CURSOR_RULES_DIR = Path(...)
* [ ] TECHNOLOGY_PATTERNS = {...}
2. Move to promptlib/types.py
:
* [ ] CursorRuleMetadata(TypedDict, total=False)
* [ ] CursorRuleExample(TypedDict)
* [ ] CursorRuleFilter(TypedDict)
* [ ] CursorRuleAction(TypedDict)
* [ ] CursorRule(TypedDict)
3. Move to promptlib/rules.py
:
* [ ] get_cursor_rule_files() -> list[Path]
* [ ] get_cursor_rule_names() -> list[str]
* [ ] read_cursor_rule(rule_name: str) -> str | None
* [ ] parse_cursor_rule(content: str) -> dict[str, Any]
* [ ] generate_cursor_rule(...) -> str
* [ ] Ensure necessary imports (glob
, json
, re
, Path
, os
, typing
, constants
, types
) are added here.
4. Move Functions to promptlib/resources.py
(Implementations Only):
* [ ] Define list_cursor_rules_impl() -> list[dict[str, str]] | dict[str, Any]
(function body of list_cursor_rules
)
* [ ] Define get_cursor_rule_impl(name: str) -> dict[str, Any]
(function body of get_cursor_rule
)
* [ ] Define get_cursor_rule_raw_impl(name: str) -> str
(function body of get_cursor_rule_raw
)
* [ ] Add necessary imports (rules
, typing
, Any
). Do not add @mcp.resource
decorators here.
5. Move Functions to promptlib/prompts.py
(Implementations Only):
* [ ] Define repo_analysis_prompt_impl(...) -> list[dict[str, Any]]
(function body of repo_analysis_prompt
)
* [ ] Define generate_cursor_rule_prompt_impl(...) -> list[dict[str, Any]]
(function body of generate_cursor_rule_prompt
)
* [ ] Add necessary imports (json
, typing
, rules
, Context
). Do not add @mcp.prompt
decorators here.
6. Move Functions to promptlib/tools.py
(Implementations Only):
* [ ] Define instruct_repo_analysis_impl() -> dict[str, Any]
* [ ] Define instruct_custom_repo_rules_generation_impl(...) -> dict[str, Any]
* [ ] Define get_static_cursor_rule_impl(...) -> dict[str, str | bool | list[dict[str, str]]]
* [ ] Define get_static_cursor_rules_impl(...) -> dict[str, list[dict[str, str | bool | list[dict[str, str]]]]]
* [ ] Define save_cursor_rule_impl(...) -> dict[str, list[dict[str, str | dict[str, bool | str]]] | str]
* [ ] Define recommend_cursor_rules_impl(...) -> list[dict[str, str | list[str]]] | dict[str, bool | list[dict[str, str]]]
* [ ] Define prep_workspace_impl() -> dict[str, str]
* [ ] Define create_cursor_rule_files_impl(...) -> dict[str, Any]
* [ ] Define ensure_makefile_task_impl(...) -> dict[str, Any]
* [ ] Define ensure_ai_report_impl(...) -> dict[str, Any]
* [ ] Define run_update_cursor_rules_impl() -> dict[str, Any]
* [ ] Define update_dockerignore_impl() -> dict[str, Any]
* [ ] Define cursor_rules_workflow_impl(...) -> dict[str, Any]
(Note: This calls other tools directly, ensure imports are correct)
* [ ] Add necessary imports (Field
, Path
, os
, re
, json
, typing
, constants
, rules
). Do not add @mcp.tool
decorators here.
7. Move Functions to promptlib/workflow.py
(Implementations Only):
* [ ] Define plan_and_execute_prompt_library_workflow_impl(...) -> dict[str, Any]
* [ ] Define execute_phase_1_impl(...) -> dict[str, Any]
* [ ] Define execute_phase_2_impl(...) -> dict[str, Any]
* [ ] Define execute_phase_3_impl(...) -> dict[str, Any]
* [ ] Define execute_phase_4_impl(...) -> dict[str, Any]
* [ ] Define execute_phase_5_impl(...) -> dict[str, Any]
* [ ] Add necessary imports (Field
, typing
, Any
, prompts
, tools
). Do not add @mcp.tool
decorators here.
8. Create promptlib/server.py
:
* [ ] Add imports: FastMCP
from mcp.server.fastmcp
, resources
, prompts
, tools
, workflow
.
* [ ] Define mcp = FastMCP("prompt_library", debug=True, log_level="DEBUG")
.
* [ ] Register resources:
```python
@mcp.resource("cursor-rules://list", ...)
def list_cursor_rules():
return resources.list_cursor_rules_impl()
@mcp.resource("cursor-rule://{name}", ...)
def get_cursor_rule(name: str):
return resources.get_cursor_rule_impl(name)
@mcp.resource("cursor-rule-raw://{name}", ...)
def get_cursor_rule_raw(name: str):
return resources.get_cursor_rule_raw_impl(name)
```
* [ ] Register prompts (similarly, calling `prompts.<func_name>_impl`).
* [ ] Register tools (similarly, calling `tools.<func_name>_impl` and `workflow.<func_name>_impl`). Remember to copy the `Field` definitions for arguments into the registration function signatures here.
* [ ] Define `def run_server(): mcp.run()`.
9. Update src/codegen_lab/__main__.py
:
* [ ] Remove old prompt_library
logic if any.
* [ ] Add from .promptlib.server import run_server
.
* [ ] In if __name__ == "__main__":
, call run_server()
.
10. Delete src/codegen_lab/prompt_library.py
:
* [ ] Remove the original file once all logic is migrated.
11. Add __init__.py
files:
* [ ] Ensure src/codegen_lab/promptlib/__init__.py
exists (can be empty).
This structure separates concerns effectively, makes the codebase easier to navigate, and isolates the core server setup and registration logic in server.py
. Remember to adjust imports within the new modules as needed.