Skip to main content
Glama

create_book_project

Initialize a new book project with title, genre, and author details, automatically loading it into the writing pipeline for multi-agent book creation.

Instructions

Create a new book project under book_projects/ (or STORYWRIGHT_PROJECTS_ROOT). Loads the new project.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
project_nameYes
book_titleYes
genreNo
authorsNo
projects_rootNo
third_agentsNo

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
resultYes

Implementation Reference

  • The actual implementation of create_book_project. Creates directories (book_projects/<slug>, briefs, reports, manuscript), initializes a ProjectConfig with provided parameters (defaulting third_agents to ['comedy']), saves config and an empty ContinuityLog, writes default brief templates, and binds the project to the session.
    def create_book_project(
        project_name: str,
        book_title: str,
        genre: str = "",
        authors: list[str] | None = None,
        projects_root: str | None = None,
        third_agents: list[str] | None = None,
    ) -> str:
        root = Path(projects_root).resolve() if projects_root else get_settings().projects_root.resolve()
        base_path = root / "book_projects" / project_name.strip().replace(" ", "-").lower()
        base_path.mkdir(parents=True, exist_ok=True)
        (base_path / "briefs").mkdir(exist_ok=True)
        (base_path / "reports").mkdir(exist_ok=True)
        (base_path / "manuscript").mkdir(exist_ok=True)
    
        agents = ["comedy"] if third_agents is None else list(third_agents)
        proj = ProjectConfig(
            name=book_title,
            genre=genre,
            authors=authors or [],
            base_path=base_path,
            third_agents=agents,
        )
        proj.save()
        cont = ContinuityLog()
        cont.save(base_path)
    
        (base_path / "briefs" / "writer_brief.md").write_text(get_default_writer_brief(), encoding="utf-8")
        (base_path / "briefs" / "editor_brief.md").write_text(get_default_editor_brief(), encoding="utf-8")
        (base_path / "briefs" / "comedy_brief.md").write_text(get_default_comedy_brief(), encoding="utf-8")
    
        bind_project(base_path)
        return (
            f"Created **{book_title}** at `{base_path}`.\n"
            f"Third-pass agents: {', '.join(agents)}\n\n"
            f"Next: `load_book_project(\"{base_path}\")` from another cwd, or continue — project is loaded."
        )
  • MCP tool registration via @mcp.tool() decorator. The async function create_book_project is exposed as an MCP tool and delegates to workflow.create_book_project.
    @mcp.tool()
    async def create_book_project(
        project_name: str,
        book_title: str,
        genre: str = "",
        authors: list[str] | None = None,
        projects_root: str | None = None,
        third_agents: list[str] | None = None,
    ) -> str:
        """Create a new book project under book_projects/ (or STORYWRIGHT_PROJECTS_ROOT). Loads the new project."""
        return workflow.create_book_project(
            project_name, book_title, genre, authors, projects_root, third_agents
        )
  • ProjectConfig dataclass schema — the data model used to store book project configuration (name, genre, authors, chapters, characters, etc.) that is created by create_book_project.
    @dataclass
    class ProjectConfig:
        name: str
        genre: str = ""
        authors: list[str] = field(default_factory=list)
        chapters: list[Chapter] = field(default_factory=list)
        characters: list[Character] = field(default_factory=list)
        death_schedule: list[DeathEntry] = field(default_factory=list)
        running_gags: list[RunningGag] = field(default_factory=list)
        base_path: Path = field(default_factory=Path.cwd)
        third_agents: list[str] = field(default_factory=list)
        has_deaths: bool = True
  • Settings class with projects_root defaulting to current working directory. Used by create_book_project to determine where to create the project folder.
    class Settings(BaseSettings):
        model_config = SettingsConfigDict(
            env_prefix="STORYWRIGHT_",
            env_file=".env",
            env_nested_delimiter="__",
            extra="ignore",
        )
    
        # Projects live under `{projects_root}/book_projects/<slug>/`
        projects_root: Path = Path.cwd()
        # Persist last loaded project path here (optional UX)
        state_dir: Path = Path.home() / ".storywright"
        # Model id for writer/editor/third-pass API calls (override per deployment)
        anthropic_model: str = "claude-sonnet-4-20250514"
        # Prior approved prose budget for writer prompts (controls context size)
        prior_chapters_max_words: int = 12000
        prior_chapters_max_count: int = 8
        # Anthropic API transient failures
        anthropic_max_retries: int = 2
        anthropic_retry_delay_seconds: float = 2.0
    
    
    _settings: Settings | None = None
    
    
    def get_settings() -> Settings:
        global _settings
        if _settings is None:
            _settings = Settings()
        return _settings
  • Helper functions get_default_writer_brief(), get_default_editor_brief(), and get_default_comedy_brief() that return the default brief templates written to the new project's briefs/ directory.
    def get_default_writer_brief() -> str:
        """Get the default writer brief template."""
        return WRITER_BRIEF_TEMPLATE
    
    
    def get_default_editor_brief() -> str:
        """Get the default editor brief template."""
        return EDITOR_BRIEF_TEMPLATE
    
    
    def get_default_comedy_brief() -> str:
        """Get the default comedy brief template."""
        return COMEDY_BRIEF_TEMPLATE
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description must fully disclose behavior. It only mentions creating and loading the project, but omits side effects, permissions, or error handling.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two short sentences, front-loaded with purpose, and contains no unnecessary words. It earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With 6 parameters and no parameter explanations, the description is insufficient for a creation tool. It fails to clarify key fields like project_name vs book_title or the role of optional parameters.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters1/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, and the tool description does not explain any parameters. The agent receives no meaning beyond parameter names and types.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states 'Create a new book project' with a specific verb and resource, and hints at the directory structure. It is clearly distinct from sibling tools like load_book_project.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides no guidance on when to use this tool versus alternatives (e.g., load_book_project). It lacks context for prerequisites or exclusions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/BurgersJackson/storywright-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server