slugline-mcp
The slugline-mcp server enables evidence-based screenplay analysis via MCP, using a RAG pipeline over a locally stored index of ~288,000 scenes from ~2,200 real movies. It does not generate answers itself; it retrieves real scene data to ground the calling LLM's feedback. Key capabilities:
Search for similar scenes: Perform semantic search over the index to find produced scenes structurally or tonally similar to a query scene text.
Get scene details: Fetch full text and metadata (movie, slugline, characters) for a specific scene by ID.
List indexed movies: Enumerate all films in the index with movie names and IMDb IDs.
Find mood reference scenes: Retrieve scenes that achieve a target mood (e.g., "paranoid") using a hybrid approachβprecise tag matching when available, otherwise semantic fallbackβreturning match confidence.
Provide analysis guidance: Offer instructions for the connected LLM to deliver direct, evidence-based feedback covering mood, next actions, and "X meets Y" comparisons.
All tools return real evidence from produced screenplays, enabling grounded, constructive feedback.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@slugline-mcpFind scenes with a paranoid mood"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
π¬ slugline-mcp
Brutal, evidence-based screenplay analysis β grounded in real produced scripts.
Mood, next-action suggestions, and "X meets Y" comparisons, backed by retrieval over ~2,200 real screenplays. One MCP server. Zero vibes-based feedback.
Under the hood: a full Retrieval-Augmented Generation (RAG) pipeline β chunking, vector embeddings, semantic search, and local zero-shot classification β exposed entirely as Model Context Protocol (MCP) tools, with zero LLM calls from the server itself.
slugline-mcp doesn't write or judge your scene itself β it retrieves real produced scenes similar to yours (or matching a mood you're chasing) so your own connected Claude can ground its feedback in evidence instead of guessing. It's the retrieval half of RAG, full stop: parse, embed, index, and semantically search real screenplays, then hand that grounded evidence to Claude over MCP.
β Star this repo if you find it useful.
Try it:
π¦ Install it β
uvx slugline-mcp(oruv pip install slugline-mcp), published on PyPIπ Add it to Claude Desktop β see
docs/claude_desktop.mdfor the configπ¬ Ask about your scene β "Find me real scenes similar to this one: [paste a scene]" and Claude answers grounded in actual retrieved screenplay text, not general knowledge
Note: the full ~288,000-scene reference index is published and fetched automatically β
bootstrap.pydownloads it (~1.8GB, one time, with a progress bar) on first run, so a fresh install returns real retrieval results out of the box. See If retrieval comes back empty if that download can't complete (e.g. offline).
π₯ Demo
A screen recording is still coming (see the roadmap below), but
docs/demo_walkthrough.md has a full text walkthrough with real
tool output β including both the precise tag-matched and semantic-fallback paths of
find_mood_reference_scenes β captured against an actual local test index, not fabricated.
Related MCP server: Seroost Search MCP Server
π― What is this?
slugline-mcp is an MCP (Model Context Protocol) server for screenwriters. It's a retrieval-only RAG pipeline: it parses a reference database of real movie screenplays into scenes, embeds them, and exposes semantic search over that index as MCP tools. The LLM doing the actual writing and judgment is your own Claude, connected locally β this server never calls out to an LLM itself, it just supplies the evidence.
Two engineering ideas this project is built around:
RAG, done properly: real chunking (screenplay scenes, not arbitrary token windows), a purpose-fit embedding model, a persistent vector store, and metadata filtering (mood tags computed once at index time) layered on top of semantic similarity β not just "stuff everything into a prompt."
MCP, done properly: five tools with schemas an LLM can actually reason about (
Annotated[..., Field(description=...)]throughouttools/), including a dedicatedget_analysis_styletool whose whole job is steering how the calling LLM uses the other four β prompt engineering expressed as a callable tool, not a static system prompt.
Reference data comes from rohitsaxena/MovieSum, a public Hugging Face dataset of ~2,200 movie screenplays, pre-structured into scenes with dialogue and stage directions.
π§ How the RAG Pipeline Works
Index time (once, offline, in indexing/build_index.py):
Parse β MovieSum's screenplay XML (or a user's raw pasted script, via a separate plain-text splitter) is split into scenes, not arbitrary chunks β a scene is the natural retrieval unit for screenplay feedback.
Embed β each scene's flattened text is encoded with
sentence-transformers/all-MiniLM-L6-v2into a 384-dim vector.Classify β each scene is also run once through a local zero-shot classifier (
facebook/bart-large-mnli) against a fixed mood taxonomy, so mood becomes a stored metadata field instead of something re-inferred on every query.Store β vectors + text + metadata land in a persistent Chroma collection.
Query time (every MCP tool call, in retrieval.py):
The incoming query (a scene, or a target mood) is embedded with the same model.
Chroma runs approximate nearest-neighbor search over the stored vectors β optionally pre-filtered by metadata (e.g.
mood == "paranoid") before ranking by similarity.Results are formatted into a canonical scene shape and returned as MCP tool output β raw evidence, not a generated answer.
Retrieval and generation are fully decoupled here: this server only ever does the retrieval half, and the MCP tool boundary is exactly where that handoff happens.
β¨ Features
search_similar_scenesβ semantic search for real produced scenes structurally or tonally similar to a scene you're writingget_scene_detailsβ fetch the full text and metadata for one indexed scene by idlist_indexed_moviesβ enumerate every movie currently in the reference indexfind_mood_reference_scenesβ find scenes that strongly hit a target mood (e.g. "paranoid"), for when you want to rewrite toward a mood your scene doesn't have yet β a hybrid search: free-text moods close to a precoded tag get precise tag-filtered results, anything else falls back to raw semantic search, with the method used reported back for transparency
get_analysis_styleβ instructs the connected LLM to be direct rather than encouraging, to gather evidence before writing anything, and to structure its feedback around mood, next action, and an "X meets Y" comparison β each one cited against specific retrieved scenes
MovieSum's screenplay XML is parsed into structured
Sceneobjects (slugline, action lines, dialogue, parentheticals); a separate plain-text splitter handles a user's own pasted script, which has no such structureEvery reference scene is run once through a local, free zero-shot classifier (
facebook/bart-large-mnli) at indexing time to tag its dominant mood β no per-query cost, no external APIEmbeddings use
sentence-transformers/all-MiniLM-L6-v2, stored in a local Chroma indexEnd users never build the index themselves: a
bootstrapmodule downloads the prebuilt index (published as a GitHub Release asset) on first run, showing progress since it's a ~1.8GB fetch, and falls back to clear "no index available" behavior (never a crash) if that download can't complete
π§° Tech Stack
Layer | Choice |
Architecture pattern | RAG (retrieval-augmented generation), exposed entirely as MCP tools |
Language | Python 3.11+ |
MCP framework | Official |
Embeddings / vector search | sentence-transformers ( |
Vector database | Chroma (persistent, local) |
Mood classification | Local zero-shot |
Reference dataset | rohitsaxena/MovieSum (~2,200 screenplays) |
Prebuilt index hosting | GitHub Release asset ( |
Build backend | Hatchling ( |
Package manager | |
Testing | pytest |
βοΈ Getting Started
Prerequisites
Python 3.11+
Install
From PyPI:
uvx slugline-mcp # run without installing, e.g. inside a Claude Desktop config
# or
uv pip install slugline-mcpFrom source:
git clone https://github.com/NalluriTanavreddy/slugline-mcp.git
cd slugline-mcp
uv syncRun the server
uv run python -m slugline_mcpAdd it to Claude Desktop
See docs/claude_desktop.md for the full config example β a
uvx slugline-mcp config now that it's published, or a local-checkout config for dev mode.
Build or fetch a reference index
The server needs a populated Chroma index to retrieve from. The full prebuilt index
(~288,000 scenes) is published and fetched automatically on first run β see
src/slugline_mcp/indexing/bootstrap.py. To build your own instead (e.g. a smaller local
subset for development), see docs/dataset.md.
Development setup
uv sync --extra index # adds datasets + transformers, needed only for indexing
uv run --with pytest pytest tests/See docs/testing.md for testing tools interactively with the MCP
Inspector.
π Usage
Once slugline-mcp is connected (see Add it to Claude Desktop above), just talk to Claude normally β paste a scene, describe what you're stuck on, or ask for a comparison. Claude decides which tools to call; you never call them directly.
Typical workflow
Paste a scene and ask for feedback. Claude calls
get_analysis_stylefirst (it's designed to steer the whole interaction), thensearch_similar_sceneswith your scene's text to pull real comparable scenes from the reference index.Claude cites specific movies and scenes, not vague genre talk β if it says "this reads like a beat from 8MM," that's because
search_similar_scenesactually returned that scene.Ask to see the full match. "Show me that whole scene" prompts Claude to call
get_scene_detailswith the id from the earlier search result.Ask for a mood rewrite. "Make this scene feel more paranoid" prompts
find_mood_reference_scenes("paranoid")β Claude gets back real scenes that strongly hit that mood, plus whether the match was precise (tag_matched) or a broader semantic guess (semantic_fallback).Ask what's in the reference set. "What movies do you have indexed?" calls
list_indexed_movies.
Example prompts
You ask Claude... | Tool(s) it calls |
"Here's my opening scene β what does this actually read like?" |
|
"Show me the full text of that Iron Lady scene you mentioned" |
|
"I want this argument to feel more like dread building, not just tense" |
|
"What films are actually in your reference database?" |
|
"Give me an 'X meets Y' comparison for this whole script" |
|
Tools reference
Tool | Purpose | Key parameters |
| Tone/structure instructions for the calling LLM | none |
| Semantic search for structurally/tonally similar produced scenes |
|
| Full text + metadata for one scene by id |
|
| Every movie currently in the index | none |
| Scenes that strongly hit a target mood, hybrid tag/semantic search |
|
If retrieval comes back empty
Every tool degrades gracefully instead of erroring if no reference index is available
(see retrieval.py) β you'll get empty results rather than a crash. A fresh install
downloads the real ~288,000-scene index automatically on first use (bootstrap.py, ~1.8GB,
one time), so this should only come up if that download couldn't complete. If it happens:
Confirm a Chroma index exists at
~/.slugline-mcp/chroma(or whereverSLUGLINE_MCP_PERSIST_DIRpoints).If not, check you're online and re-run β
bootstrap.pyretries the download on the next call since nothing was persisted. You can also build your own index instead (seedocs/dataset.md).
ποΈ Project Structure
src/slugline_mcp/
βββ server.py # FastMCP instance, tool registration
βββ __main__.py # `python -m slugline_mcp` entry point
βββ config.py # env var loading
βββ retrieval.py # Chroma-backed retrieval (search, get, mood filter)
βββ tools/
β βββ search_similar_scenes.py
β βββ get_scene_details.py
β βββ list_indexed_movies.py
β βββ get_analysis_style.py
β βββ find_mood_reference_scenes.py
β βββ _formatting.py # shared scene response shape
βββ indexing/
βββ parser.py # MovieSum XML -> Scene objects
βββ plaintext_scene_splitter.py # raw pasted scripts -> scenes
βββ embeddings.py # sentence-transformers wrapper
βββ mood_tagging.py # local zero-shot mood classifier
βββ chroma_client.py # Chroma persistent client/collection
βββ build_index.py # maintainer script: parse + embed + tag + store
βββ bootstrap.py # download prebuilt index from GitHub Releases
tests/ # pytest suite, one file per tool/module
docs/ # dataset, MCP Inspector testing, Claude Desktop configπΊοΈ Roadmap
Phase 0 β Repo setup: README, license,
pyproject.toml, package structurePhase 1 β Indexing pipeline: MovieSum XML parser, plain-text splitter, embeddings, Chroma,
build_index, local mood tagging, HF Hub bootstrapPhase 2 β MCP server core: FastMCP scaffold, entry point, config, retrieval logic
Phase 3 β Tools: all five tools implemented, registered, and tested
Phase 4 β Local testing: MCP Inspector docs, schema fixes, graceful empty results, Claude Desktop config, this README
Phase 5 β Packaging: console entry point, versioning,
uvxsupportPhase 6 β CI/CD: GitHub Actions build/test + PyPI publish workflows
Phase 7 β Docs & release: full usage guide, CONTRIBUTING, demo walkthrough, v0.1.0
Phase 8 β Publish: TestPyPI, then PyPI
See TASKS.md for the full task-by-task build checklist.
π License
MIT β see LICENSE.
π€ Author
Built by NalluriTanavreddy.
Available Tools
1 toolfind_mood_reference_scenesA
Find reference scenes that strongly achieve a target mood.
Returns:
A dict with:
- method: "tag_matched" if target_mood closely matched a
precoded mood tag, "semantic_fallback" if it didn't and results
came from raw nearest-neighbor search instead, or "unavailable"
if the reference index isn't available.
- matched_tag / tag_similarity: the closest precoded tag and
its cosine similarity to target_mood, regardless of which
method was used -- lets the caller judge match confidence even on
the fallback path.
- results: the ranked scene matches themselves. Empty if no
scenes are available or the index is unavailable.
| Name | Required | Description | Default |
|---|---|---|---|
| top_k | No | Maximum number of matches to return. | |
| target_mood | Yes | The mood to rewrite toward, in free text (e.g. "paranoid", "wistful", "a creeping sense of being watched"). Doesn't need to match a precoded label -- close matches use a precise tag-filtered search, anything else falls back to raw semantic search so results are still returned. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Despite no annotations, the description fully discloses behavioral traits: two search methods, conditions for each, return dict keys, and behavior when index is unavailable.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with a clear lead sentence and bulleted return section. It is thorough but could be slightly more concise.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no output schema, the description thoroughly documents return format and all scenarios. The tool's behavior is fully specified.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, but the description adds value by explaining how target_mood works (free text, fallback behavior) and clarifying top_k as maximum matches.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool finds reference scenes for a target mood, distinguishes two methods based on input closeness, and explains the return structure.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explains when each internal method is used (tag_matched vs semantic_fallback) and notes that target_mood can be free text. However, no sibling tools are listed, so no direct comparison with alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
1 tool update
v0.1.0- First observed
find_mood_reference_scenes
TDQS
Scored across 1 tool
With only a single tool, there is no possibility of ambiguity. The tool's purpose is clearly distinct as the sole entry point.
The sole tool uses a clear verb_noun pattern ('find_mood_reference_scenes'), and with only one tool, there are no inconsistencies to evaluate.
A single tool is borderline appropriate for a server focused on mood reference scenes. It feels minimal but could be acceptable if the tool itself is comprehensive. However, most servers benefit from at least a few tools.
The server exposes only a query operation. There are no tools for adding, updating, or managing scenes or moods, which leaves significant gaps for any workflow beyond simple retrieval.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
Your AI writes inside real screenplays: formatted scenes, locked numbering, outlines, research.
1AI story development, screenplay editing, review, media, and export tools for BeatBandit projects.
Search Chinese TV drama scenes with second-level timestamps by character, emotion, or scene type.
Film stills from 5,489 films, searchable by lighting, lens character, shot size, colour and mood.
Related MCP Servers
- -licenseNot gradedqualityNot gradedmaintenanceEnables deep analysis of SEC EDGAR filings through universal company search, document content extraction, and advanced filing search capabilities. Provides AI-ready access to business descriptions, risk factors, financial statements, and full-text search across any public company's SEC documents.-
- FlicenseAqualityDmaintenanceEnables AI agents to perform semantic code search across entire codebases using natural language queries. Provides fast indexing and ranked search results with line numbers and file paths through the Seroost search engine.387-
- AlicenseNot gradedqualityCmaintenanceAn MCP service for AI-assisted reasoning and editing on long-form fiction projects. It builds a structured index from scene files for targeted context retrieval.2731AGPL 3.0
- FlicenseNot gradedqualityCmaintenanceAn MCP server providing 67 tools for AI-assisted storywriting, world-building, character development, screenplay generation in industry formats (Fountain, FDX, PDF), storyboards, and production analytics.-