novelai_image_mcp.nai — NovelAI HTTP client

The nai/ subpackage is the NovelAI HTTP client. It is MCP-agnostic — it can be used standalone from any async Python code, independent of the MCP server.

Submodules

novelai_image_mcp.nai.client

The high-level async client. Wraps the wire-format encoder (payload.build_generation_payload) and response decoder (response.parse_messagepack_images) over a shared httpx.AsyncClient.

Complete NovelAI HTTP client built on a shared httpx async session.

A long-lived httpx.AsyncClient is owned by the instance (or supplied by the MCP lifespan) and used for all NovelAI API traffic. Covers generation, Director, utility, and account business logic.

exception novelai_image_mcp.nai.client.MissingNovelAITokenError[source]

Bases: NovelAIAuthenticationError

No usable NovelAI credential is configured.

class novelai_image_mcp.nai.client.NovelAIClient(credentials, *, http_client=None, image_base_url='https://image.novelai.net', account_base_url='https://api.novelai.net', timeout=120.0, vibe_cache_entries=64)[source]

Bases: object

Project-owned client for generation, tools, utilities, and account APIs.

Parameters:
async aclose()[source]

Close the underlying HTTP session when owned by this client.

Return type:

None

async get_access_token()[source]
Return type:

str

async encode_vibe(reference, *, information_extracted, model)[source]
Parameters:
Return type:

str

async generate(request)[source]
Parameters:

request (GenerationRequest)

Return type:

tuple[NovelAIImage, …]

async stream_generation(request)[source]

Yield V4/V4.5 events as the active driver produces HTTP chunks.

Parameters:

request (GenerationRequest)

Return type:

AsyncIterator[GenerationEvent]

async director(tool, image, *, prompt='', defry=0, emotion=None, emotion_level=EmotionLevel.NORMAL)[source]
Parameters:
Return type:

NovelAIImage

async upscale(image, *, factor=4)[source]
Parameters:
Return type:

NovelAIImage

async annotate(image, model)[source]
Parameters:
Return type:

NovelAIImage

async suggest_tags(prompt, *, model=Model.V4_5, language='en')[source]
Parameters:
Return type:

tuple[dict[str, Any], …]

async get_subscription()[source]
Return type:

dict[str, Any]

async get_user_data()[source]
Return type:

dict[str, Any]

exception novelai_image_mcp.nai.client.NovelAIError[source]

Bases: Exception

Base class for NovelAI failures.

exception novelai_image_mcp.nai.client.NovelAIProviderError[source]

Bases: NovelAIError

NovelAI rejected or failed the request.

exception novelai_image_mcp.nai.client.NovelAIResponseError[source]

Bases: NovelAIError

NovelAI returned malformed or unsupported data.

exception novelai_image_mcp.nai.client.NovelAITimeoutError[source]

Bases: NovelAIError

A request exceeded its timeout.

exception novelai_image_mcp.nai.client.NovelAITransportError[source]

Bases: NovelAIError

The request could not reach NovelAI.

novelai_image_mcp.nai.client.extract_final_image(content)[source]
Parameters:

content (bytes)

Return type:

bytes

async novelai_image_mcp.nai.client.generate_image_from_plan(plan, *, client, n_samples=1, quality=True, uc_preset=0, noise_schedule='karras', cfg_rescale=0.0, dynamic_thresholding=False, auto_smea=False, prefer_brownian=True)[source]

Generate a single image from a high-level plan (used by the sync CLI).

The caller supplies the configured client plus the generation defaults (read from settings, not from a global config).

Parameters:
Return type:

bytes

novelai_image_mcp.nai.constants

Enums for the NovelAI API surface: Action, Model, Sampler, DirectorTool, Emotion, EmotionLevel, ControlNetModel, Endpoint, NoiseSchedule. Plus the predicates is_v4_model and is_inpaint_model.

NovelAI protocol constants and model capability helpers.

class novelai_image_mcp.nai.constants.IntEnum(new_class_name, /, names, *, module=None, qualname=None, type=None, start=1, boundary=None)[source]

Bases: int, ReprEnum

Enum where members are also (and must be) ints

class novelai_image_mcp.nai.constants.StrEnum(new_class_name, /, names, *, module=None, qualname=None, type=None, start=1, boundary=None)[source]

Bases: str, ReprEnum

Enum where members are also (and must be) strings

__new_member__(*values)

values must already be of type str

class novelai_image_mcp.nai.constants.Endpoint(*values)[source]

Bases: StrEnum

LOGIN = '/user/login'
USER_DATA = '/user/data'
SUBSCRIPTION = '/user/subscription'
IMAGE = '/ai/generate-image'
IMAGE_STREAM = '/ai/generate-image-stream'
DIRECTOR = '/ai/augment-image'
ENCODE_VIBE = '/ai/encode-vibe'
UPSCALE = '/ai/upscale'
ANNOTATE = '/ai/annotate-image'
SUGGEST_TAGS = '/ai/generate-image/suggest-tags'
class novelai_image_mcp.nai.constants.Model(*values)[source]

Bases: StrEnum

V3 = 'nai-diffusion-3'
V3_INPAINT = 'nai-diffusion-3-inpainting'
FURRY = 'nai-diffusion-furry-3'
FURRY_INPAINT = 'nai-diffusion-furry-3-inpainting'
V4 = 'nai-diffusion-4-full'
V4_INPAINT = 'nai-diffusion-4-full-inpainting'
V4_CURATED = 'nai-diffusion-4-curated-preview'
V4_CURATED_INPAINT = 'nai-diffusion-4-curated-inpainting'
V4_5 = 'nai-diffusion-4-5-full'
V4_5_INPAINT = 'nai-diffusion-4-5-full-inpainting'
V4_5_CURATED = 'nai-diffusion-4-5-curated'
V4_5_CURATED_INPAINT = 'nai-diffusion-4-5-curated-inpainting'
class novelai_image_mcp.nai.constants.Action(*values)[source]

Bases: StrEnum

GENERATE = 'generate'
IMG2IMG = 'img2img'
INPAINT = 'infill'
class novelai_image_mcp.nai.constants.Sampler(*values)[source]

Bases: StrEnum

EULER = 'k_euler'
EULER_ANCESTRAL = 'k_euler_ancestral'
DPM_2S_ANCESTRAL = 'k_dpmpp_2s_ancestral'
DPM_2M = 'k_dpmpp_2m'
DPM_2M_SDE = 'k_dpmpp_2m_sde'
DPM_SDE = 'k_dpmpp_sde'
DDIM = 'ddim_v3'
class novelai_image_mcp.nai.constants.NoiseSchedule(*values)[source]

Bases: StrEnum

NATIVE = 'native'
KARRAS = 'karras'
EXPONENTIAL = 'exponential'
POLYEXPONENTIAL = 'polyexponential'
class novelai_image_mcp.nai.constants.ControlNetModel(*values)[source]

Bases: StrEnum

PALETTE_SWAP = 'hed'
FORM_LOCK = 'midas'
SCRIBBLER = 'fake_scribble'
BUILDING_CONTROL = 'mlsd'
LANDSCAPER = 'uniformer'
class novelai_image_mcp.nai.constants.DirectorTool(*values)[source]

Bases: StrEnum

LINE_ART = 'lineart'
SKETCH = 'sketch'
BACKGROUND_REMOVAL = 'bg-removal'
DECLUTTER = 'declutter'
COLORIZE = 'colorize'
EMOTION = 'emotion'
class novelai_image_mcp.nai.constants.Emotion(*values)[source]

Bases: StrEnum

NEUTRAL = 'neutral'
HAPPY = 'happy'
SAD = 'sad'
ANGRY = 'angry'
SCARED = 'scared'
SURPRISED = 'surprised'
TIRED = 'tired'
EXCITED = 'excited'
NERVOUS = 'nervous'
THINKING = 'thinking'
CONFUSED = 'confused'
SHY = 'shy'
DISGUSTED = 'disgusted'
SMUG = 'smug'
BORED = 'bored'
LAUGHING = 'laughing'
IRRITATED = 'irritated'
AROUSED = 'aroused'
EMBARRASSED = 'embarrassed'
WORRIED = 'worried'
LOVE = 'love'
DETERMINED = 'determined'
HURT = 'hurt'
PLAYFUL = 'playful'
class novelai_image_mcp.nai.constants.EmotionLevel(*values)[source]

Bases: IntEnum

NORMAL = 0
SLIGHTLY_WEAK = 1
WEAK = 2
EVEN_WEAKER = 3
VERY_WEAK = 4
WEAKEST = 5
novelai_image_mcp.nai.constants.is_v4_model(model)[source]
Parameters:

model (Model)

Return type:

bool

novelai_image_mcp.nai.constants.is_inpaint_model(model)[source]
Parameters:

model (Model)

Return type:

bool

novelai_image_mcp.nai.models

Pydantic models for the wire format: GenerationRequest, CharacterPrompt, NovelAIGenerationPlan.

Pure value objects shared by the NovelAI generation pipeline.

novelai_image_mcp.nai.models.dataclass(cls=None, /, *, init=True, repr=True, eq=True, order=False, unsafe_hash=False, frozen=False, match_args=True, kw_only=False, slots=False, weakref_slot=False)[source]

Add dunder methods based on the fields defined in the class.

Examines PEP 526 __annotations__ to determine fields.

If init is true, an __init__() method is added to the class. If repr is true, a __repr__() method is added. If order is true, rich comparison dunder methods are added. If unsafe_hash is true, a __hash__() method is added. If frozen is true, fields may not be assigned to after instance creation. If match_args is true, the __match_args__ tuple is added. If kw_only is true, then by default all fields are keyword-only. If slots is true, a new class with a __slots__ attribute is returned.

class novelai_image_mcp.nai.models.Action(*values)[source]

Bases: StrEnum

GENERATE = 'generate'
IMG2IMG = 'img2img'
INPAINT = 'infill'
class novelai_image_mcp.nai.models.Model(*values)[source]

Bases: StrEnum

V3 = 'nai-diffusion-3'
V3_INPAINT = 'nai-diffusion-3-inpainting'
FURRY = 'nai-diffusion-furry-3'
FURRY_INPAINT = 'nai-diffusion-furry-3-inpainting'
V4 = 'nai-diffusion-4-full'
V4_INPAINT = 'nai-diffusion-4-full-inpainting'
V4_CURATED = 'nai-diffusion-4-curated-preview'
V4_CURATED_INPAINT = 'nai-diffusion-4-curated-inpainting'
V4_5 = 'nai-diffusion-4-5-full'
V4_5_INPAINT = 'nai-diffusion-4-5-full-inpainting'
V4_5_CURATED = 'nai-diffusion-4-5-curated'
V4_5_CURATED_INPAINT = 'nai-diffusion-4-5-curated-inpainting'
class novelai_image_mcp.nai.models.NoiseSchedule(*values)[source]

Bases: StrEnum

NATIVE = 'native'
KARRAS = 'karras'
EXPONENTIAL = 'exponential'
POLYEXPONENTIAL = 'polyexponential'
class novelai_image_mcp.nai.models.Sampler(*values)[source]

Bases: StrEnum

EULER = 'k_euler'
EULER_ANCESTRAL = 'k_euler_ancestral'
DPM_2S_ANCESTRAL = 'k_dpmpp_2s_ancestral'
DPM_2M = 'k_dpmpp_2m'
DPM_2M_SDE = 'k_dpmpp_2m_sde'
DPM_SDE = 'k_dpmpp_sde'
DDIM = 'ddim_v3'
novelai_image_mcp.nai.models.is_inpaint_model(model)[source]
Parameters:

model (Model)

Return type:

bool

novelai_image_mcp.nai.models.normalize_tags(values)[source]

Trim tags and remove case-insensitive duplicates while preserving order.

Parameters:

values (tuple[str, ...])

Return type:

tuple[str, …]

novelai_image_mcp.nai.models.normalize_negative_prompt(value)[source]

Split comma/newline negative prompt text into normalized tags.

Parameters:

value (str | None)

Return type:

tuple[str, …]

class novelai_image_mcp.nai.models.PositionCoord(x: 'float', y: 'float')[source]

Bases: object

Parameters:
x: float
y: float
class novelai_image_mcp.nai.models.CharacterIntent(description: 'str', tags: 'tuple[str, ...]', negative_tags: 'tuple[str, ...]', center: 'PositionCoord')[source]

Bases: object

Parameters:
description: str
tags: tuple[str, ...]
negative_tags: tuple[str, ...]
center: PositionCoord
class novelai_image_mcp.nai.models.GenerationHints(width: 'int | None' = None, height: 'int | None' = None, steps: 'int | None' = None, scale: 'float | None' = None, sampler: 'str | None' = None, seed: 'int | None' = None, negative_tags: 'tuple[str, ...]' = ())[source]

Bases: object

Parameters:
  • width (int | None)

  • height (int | None)

  • steps (int | None)

  • scale (float | None)

  • sampler (str | None)

  • seed (int | None)

  • negative_tags (tuple[str, ...])

width: int | None
height: int | None
steps: int | None
scale: float | None
sampler: str | None
seed: int | None
negative_tags: tuple[str, ...]
class novelai_image_mcp.nai.models.PromptIntent(source_language: 'str', english_description: 'str', base_tags: 'tuple[str, ...]', generation: 'GenerationHints', characters: 'tuple[CharacterIntent, ...]', search_required: 'bool', search_query: 'str | None', search_reason: 'str | None')[source]

Bases: object

Parameters:
source_language: str
english_description: str
base_tags: tuple[str, ...]
generation: GenerationHints
characters: tuple[CharacterIntent, ...]
search_required: bool
search_query: str | None
search_reason: str | None
class novelai_image_mcp.nai.models.VisualResearch(facts: 'tuple[str, ...]', sources: 'tuple[str, ...]')[source]

Bases: object

Parameters:
facts: tuple[str, ...]
sources: tuple[str, ...]
class novelai_image_mcp.nai.models.TipoRequest(description: 'str', tags: 'tuple[str, ...]', visual_facts: 'tuple[str, ...]', seed: 'int')[source]

Bases: object

Parameters:
description: str
tags: tuple[str, ...]
visual_facts: tuple[str, ...]
seed: int
class novelai_image_mcp.nai.models.TipoPrompt(natural_language: 'str', tags: 'tuple[str, ...]')[source]

Bases: object

Parameters:
natural_language: str
tags: tuple[str, ...]
class novelai_image_mcp.nai.models.GenerationOverrides(width: 'int | None' = None, height: 'int | None' = None, steps: 'int | None' = None, scale: 'float | None' = None, sampler: 'str | None' = None, seed: 'int | None' = None, negative_prompt: 'str | None' = None)[source]

Bases: object

Parameters:
  • width (int | None)

  • height (int | None)

  • steps (int | None)

  • scale (float | None)

  • sampler (str | None)

  • seed (int | None)

  • negative_prompt (str | None)

width: int | None
height: int | None
steps: int | None
scale: float | None
sampler: str | None
seed: int | None
negative_prompt: str | None
class novelai_image_mcp.nai.models.NovelAIGenerationPlan(prompt: 'str', negative_prompt: 'str', width: 'int', height: 'int', steps: 'int', scale: 'float', sampler: 'str', seed: 'int', base_caption: 'str', char_captions: 'tuple[dict[str, object], ...]', character_prompts: 'tuple[dict[str, object], ...]', use_coords: 'bool')[source]

Bases: object

Parameters:
prompt: str
negative_prompt: str
width: int
height: int
steps: int
scale: float
sampler: str
seed: int
base_caption: str
char_captions: tuple[dict[str, object], ...]
character_prompts: tuple[dict[str, object], ...]
use_coords: bool
class novelai_image_mcp.nai.models.CharacterPrompt(prompt: 'str', negative_prompt: 'str' = '', x: 'float' = 0.5, y: 'float' = 0.5, enabled: 'bool' = True)[source]

Bases: object

Parameters:
prompt: str
negative_prompt: str
x: float
y: float
enabled: bool
class novelai_image_mcp.nai.models.GenerationRequest(prompt, base_caption=None, model=Model.V4_5, action=Action.GENERATE, negative_prompt='', width=832, height=1216, n_samples=1, steps=28, scale=5.0, sampler=Sampler.EULER_ANCESTRAL, seed=0, extra_noise_seed=None, noise_schedule=NoiseSchedule.KARRAS, quality=True, uc_preset=0, dynamic_thresholding=False, cfg_rescale=0.0, smea=None, smea_dynamic=None, auto_smea=False, image=None, mask=None, strength=None, noise=None, add_original_image=True, controlnet_strength=1.0, controlnet_condition=None, controlnet_model=None, references=(), reference_information=(), reference_strengths=(), character_prompts=(), use_coords=False, use_order=True, legacy_uc=False, normalize_reference_strengths=True, deliberate_euler_ancestral_bug=False, prefer_brownian=True, skip_cfg_above_sigma=None, legacy=False, legacy_v3_extend=False, inpaint_img2img_strength=None)[source]

Bases: object

Complete NovelAI generation request independent of the chat planner.

Parameters:
prompt: str
base_caption: str | None
model: Model
action: Action
negative_prompt: str
width: int
height: int
n_samples: int
steps: int
scale: float
sampler: Sampler | str
seed: int
extra_noise_seed: int | None
noise_schedule: NoiseSchedule | str
quality: bool
uc_preset: int
dynamic_thresholding: bool
cfg_rescale: float
smea: bool | None
smea_dynamic: bool | None
auto_smea: bool
image: str | None
mask: str | None
strength: float | None
noise: float | None
add_original_image: bool
controlnet_strength: float
controlnet_condition: str | None
controlnet_model: str | None
references: tuple[str, ...]
reference_information: tuple[float, ...]
reference_strengths: tuple[float, ...]
character_prompts: tuple[CharacterPrompt, ...]
use_coords: bool
use_order: bool
legacy_uc: bool
normalize_reference_strengths: bool
deliberate_euler_ancestral_bug: bool
prefer_brownian: bool
skip_cfg_above_sigma: int | None
legacy: bool
legacy_v3_extend: bool
inpaint_img2img_strength: int | None
property effective_prompt: str
property effective_base_caption: str
property effective_negative_prompt: str
property max_samples: int
estimate_anlas_cost(*, opus=False)[source]

Estimate provider Anlas cost using the public web-client formula.

Parameters:

opus (bool)

Return type:

int

novelai_image_mcp.nai.auth

Argon2id access-key derivation + per-request tracking headers.

NovelAI credential validation and access-key derivation.

novelai_image_mcp.nai.auth.dataclass(cls=None, /, *, init=True, repr=True, eq=True, order=False, unsafe_hash=False, frozen=False, match_args=True, kw_only=False, slots=False, weakref_slot=False)[source]

Add dunder methods based on the fields defined in the class.

Examines PEP 526 __annotations__ to determine fields.

If init is true, an __init__() method is added to the class. If repr is true, a __repr__() method is added. If order is true, rich comparison dunder methods are added. If unsafe_hash is true, a __hash__() method is added. If frozen is true, fields may not be assigned to after instance creation. If match_args is true, the __match_args__ tuple is added. If kw_only is true, then by default all fields are keyword-only. If slots is true, a new class with a __slots__ attribute is returned.

class novelai_image_mcp.nai.auth.datetime(year, month, day[, hour[, minute[, second[, microsecond[, tzinfo]]]]])

Bases: date

The year, month and day arguments are required. tzinfo may be None, or an instance of a tzinfo subclass. The remaining arguments may be ints.

astimezone()

tz -> convert to local time in new timezone tz

classmethod combine()

date, time -> datetime with same date and time fields

ctime()

Return ctime() style string.

date()

Return date object with same year, month and day.

dst()

Return self.tzinfo.dst(self).

fold
classmethod fromisoformat(object, /)

string -> datetime from a string in most ISO 8601 formats

classmethod fromtimestamp()

timestamp[, tz] -> tz’s local time from POSIX timestamp.

hour
isoformat()

[sep] -> string in ISO 8601 format, YYYY-MM-DDT[HH[:MM[:SS[.mmm[uuu]]]]][+HH:MM]. sep is used to separate the year from the time, and defaults to ‘T’. The optional argument timespec specifies the number of additional terms of the time to include. Valid options are ‘auto’, ‘hours’, ‘minutes’, ‘seconds’, ‘milliseconds’ and ‘microseconds’.

max = datetime.datetime(9999, 12, 31, 23, 59, 59, 999999)
microsecond
min = datetime.datetime(1, 1, 1, 0, 0)
minute
classmethod now(tz=None)

Returns new datetime object representing current time local to tz.

tz

Timezone object.

If no tz is specified, uses local timezone.

replace()

Return datetime with new specified fields.

resolution = datetime.timedelta(microseconds=1)
second
classmethod strptime()

string, format -> new datetime parsed from a string (like time.strptime()).

time()

Return time object with same time but with tzinfo=None.

timestamp()

Return POSIX timestamp as float.

timetuple()

Return time tuple, compatible with time.localtime().

timetz()

Return time object with same time and tzinfo.

tzinfo
tzname()

Return self.tzinfo.tzname(self).

classmethod utcfromtimestamp()

Construct a naive UTC datetime from a POSIX timestamp.

classmethod utcnow()

Return a new datetime representing UTC day and time.

utcoffset()

Return self.tzinfo.utcoffset(self).

utctimetuple()

Return UTC time tuple, compatible with time.localtime().

class novelai_image_mcp.nai.auth.blake2b(data=b'', *, digest_size=64, key=b'', salt=b'', person=b'', fanout=1, depth=1, leaf_size=0, node_offset=0, node_depth=0, inner_size=0, last_node=False, usedforsecurity=True, string=None)

Bases: object

Return a new BLAKE2b hash object.

MAX_DIGEST_SIZE = 64
MAX_KEY_SIZE = 64
PERSON_SIZE = 16
SALT_SIZE = 16
block_size
copy()

Return a copy of the hash object.

digest()

Return the digest value as a bytes object.

digest_size
hexdigest()

Return the digest value as a string of hexadecimal digits.

name
update(data, /)

Update this hash object’s state with the provided bytes-like object.

class novelai_image_mcp.nai.auth.NovelAICredentials(token: 'str | None' = None, username: 'str | None' = None, password: 'str | None' = None)[source]

Bases: object

Parameters:
  • token (str | None)

  • username (str | None)

  • password (str | None)

token: str | None
username: str | None
password: str | None
novelai_image_mcp.nai.auth.derive_access_key(credentials)[source]

Derive the 64-character NovelAI login key from username/password.

Parameters:

credentials (NovelAICredentials)

Return type:

str

novelai_image_mcp.nai.auth.request_tracking_headers()[source]

Build fresh tracking headers expected by NovelAI’s browser-facing APIs.

Return type:

dict[str, str]

novelai_image_mcp.nai.payload

build_generation_payload — wire-format encoder (MessagePack-compatible).

NovelAI V4.5 wire payload mapping.

novelai_image_mcp.nai.payload.is_v4_model(model)[source]
Parameters:

model (Model)

Return type:

bool

class novelai_image_mcp.nai.payload.GenerationRequest(prompt, base_caption=None, model=Model.V4_5, action=Action.GENERATE, negative_prompt='', width=832, height=1216, n_samples=1, steps=28, scale=5.0, sampler=Sampler.EULER_ANCESTRAL, seed=0, extra_noise_seed=None, noise_schedule=NoiseSchedule.KARRAS, quality=True, uc_preset=0, dynamic_thresholding=False, cfg_rescale=0.0, smea=None, smea_dynamic=None, auto_smea=False, image=None, mask=None, strength=None, noise=None, add_original_image=True, controlnet_strength=1.0, controlnet_condition=None, controlnet_model=None, references=(), reference_information=(), reference_strengths=(), character_prompts=(), use_coords=False, use_order=True, legacy_uc=False, normalize_reference_strengths=True, deliberate_euler_ancestral_bug=False, prefer_brownian=True, skip_cfg_above_sigma=None, legacy=False, legacy_v3_extend=False, inpaint_img2img_strength=None)[source]

Bases: object

Complete NovelAI generation request independent of the chat planner.

Parameters:
prompt: str
base_caption: str | None
model: Model
action: Action
negative_prompt: str
width: int
height: int
n_samples: int
steps: int
scale: float
sampler: Sampler | str
seed: int
extra_noise_seed: int | None
noise_schedule: NoiseSchedule | str
quality: bool
uc_preset: int
dynamic_thresholding: bool
cfg_rescale: float
smea: bool | None
smea_dynamic: bool | None
auto_smea: bool
image: str | None
mask: str | None
strength: float | None
noise: float | None
add_original_image: bool
controlnet_strength: float
controlnet_condition: str | None
controlnet_model: str | None
references: tuple[str, ...]
reference_information: tuple[float, ...]
reference_strengths: tuple[float, ...]
character_prompts: tuple[CharacterPrompt, ...]
use_coords: bool
use_order: bool
legacy_uc: bool
normalize_reference_strengths: bool
deliberate_euler_ancestral_bug: bool
prefer_brownian: bool
skip_cfg_above_sigma: int | None
legacy: bool
legacy_v3_extend: bool
inpaint_img2img_strength: int | None
property effective_base_caption: str
property effective_negative_prompt: str
property effective_prompt: str
estimate_anlas_cost(*, opus=False)[source]

Estimate provider Anlas cost using the public web-client formula.

Parameters:

opus (bool)

Return type:

int

property max_samples: int
class novelai_image_mcp.nai.payload.NovelAIGenerationPlan(prompt: 'str', negative_prompt: 'str', width: 'int', height: 'int', steps: 'int', scale: 'float', sampler: 'str', seed: 'int', base_caption: 'str', char_captions: 'tuple[dict[str, object], ...]', character_prompts: 'tuple[dict[str, object], ...]', use_coords: 'bool')[source]

Bases: object

Parameters:
prompt: str
negative_prompt: str
width: int
height: int
steps: int
scale: float
sampler: str
seed: int
base_caption: str
char_captions: tuple[dict[str, object], ...]
character_prompts: tuple[dict[str, object], ...]
use_coords: bool
novelai_image_mcp.nai.payload.build_payload(plan, *, model)[source]

Map an already-resolved plan to NovelAI’s V4.5 request shape.

Parameters:
Return type:

dict[str, Any]

novelai_image_mcp.nai.payload.build_generation_payload(request)[source]

Serialize every supported generation and conditioning option.

Parameters:

request (GenerationRequest)

Return type:

dict[str, Any]

novelai_image_mcp.nai.response

Response parsing: NovelAIImage, parse_messagepack_images, parse_zip_images, check_status, GenerationEvent.

NovelAI HTTP, ZIP, and MessagePack response parsing.

novelai_image_mcp.nai.response.dataclass(cls=None, /, *, init=True, repr=True, eq=True, order=False, unsafe_hash=False, frozen=False, match_args=True, kw_only=False, slots=False, weakref_slot=False)[source]

Add dunder methods based on the fields defined in the class.

Examines PEP 526 __annotations__ to determine fields.

If init is true, an __init__() method is added to the class. If repr is true, a __repr__() method is added. If order is true, rich comparison dunder methods are added. If unsafe_hash is true, a __hash__() method is added. If frozen is true, fields may not be assigned to after instance creation. If match_args is true, the __match_args__ tuple is added. If kw_only is true, then by default all fields are keyword-only. If slots is true, a new class with a __slots__ attribute is returned.

class novelai_image_mcp.nai.response.Any(*args, **kwargs)[source]

Bases: object

Special type indicating an unconstrained type.

  • Any is assignable to every type.

  • Any assumed to have all methods and attributes.

  • All values are assignable to Any.

Note that all the above statements are true from the point of view of static type checkers. At runtime, Any cannot be used with instance checks.

novelai_image_mcp.nai.response.cast(typ, val)[source]

Cast a value to a type.

This returns the value unchanged. To the type checker this signals that the return value has the designated type, but at runtime we intentionally don’t check anything (we want this to be as fast as possible).

class novelai_image_mcp.nai.response.NovelAIImage(filename: 'str', data: 'bytes')[source]

Bases: object

Parameters:
filename: str
data: bytes
class novelai_image_mcp.nai.response.GenerationEvent(event_type: 'str', sample_index: 'int', step_index: 'int', generation_id: 'str', sigma: 'float', image: 'NovelAIImage')[source]

Bases: object

Parameters:
event_type: str
sample_index: int
step_index: int
generation_id: str
sigma: float
image: NovelAIImage
novelai_image_mcp.nai.response.check_status(status_code, content)[source]

Raise the domain error associated with an HTTP status.

Parameters:
Return type:

None

novelai_image_mcp.nai.response.parse_zip_images(content)[source]
Parameters:

content (bytes)

Return type:

tuple[NovelAIImage, …]

class novelai_image_mcp.nai.response.MessagePackStreamParser[source]

Bases: object

Incrementally parse NovelAI’s big-endian length-prefixed MessagePack.

feed(chunk)[source]
Parameters:

chunk (bytes)

Return type:

tuple[GenerationEvent, …]

finish()[source]
Return type:

None

novelai_image_mcp.nai.response.parse_messagepack_events(content)[source]
Parameters:

content (bytes)

Return type:

tuple[GenerationEvent, …]

novelai_image_mcp.nai.response.parse_messagepack_images(content)[source]
Parameters:

content (bytes)

Return type:

tuple[NovelAIImage, …]

Note

The exception classes listed above are imported into response for raising in check_status; they are documented under their defining module, novelai_image_mcp.nai.exceptions (see the next subsection).

novelai_image_mcp.nai.exceptions

Domain exception hierarchy:

Typed NovelAI domain failures.

exception novelai_image_mcp.nai.exceptions.NovelAIError[source]

Bases: Exception

Base class for NovelAI failures.

exception novelai_image_mcp.nai.exceptions.NovelAIProviderError[source]

Bases: NovelAIError

NovelAI rejected or failed the request.

exception novelai_image_mcp.nai.exceptions.NovelAIValidationError[source]

Bases: NovelAIProviderError

The request is invalid.

exception novelai_image_mcp.nai.exceptions.NovelAIAuthenticationError[source]

Bases: NovelAIProviderError

Credentials are missing, invalid, or expired.

exception novelai_image_mcp.nai.exceptions.NovelAIInsufficientCreditsError[source]

Bases: NovelAIProviderError

The account has insufficient Anlas or no subscription.

exception novelai_image_mcp.nai.exceptions.NovelAIConcurrencyError[source]

Bases: NovelAIProviderError

The account hit a concurrency or rate limit.

exception novelai_image_mcp.nai.exceptions.NovelAITimeoutError[source]

Bases: NovelAIError

A request exceeded its timeout.

exception novelai_image_mcp.nai.exceptions.NovelAITransportError[source]

Bases: NovelAIError

The request could not reach NovelAI.

exception novelai_image_mcp.nai.exceptions.NovelAIResponseError[source]

Bases: NovelAIError

NovelAI returned malformed or unsupported data.

exception novelai_image_mcp.nai.exceptions.NovelAIImageError[source]

Bases: NovelAIError

An input or output image is malformed or unsupported.

novelai_image_mcp.nai.service

create_novelai_client factory + NovelAIConfigLike protocol. The factory takes a settings-like object and an httpx.AsyncClient, returns a fully wired NovelAIClient.

High-level NovelAI service construction for the MCP server and CLI consumers.

A duck-typed config object (NovelAIConfigLike Protocol) keeps the nai package decoupled from the MCP wrapper. The wrapper’s NovelAISettings (pydantic-settings, env-driven) satisfies this protocol structurally; see novelai_image_mcp.settings.

class novelai_image_mcp.nai.service.NovelAIConfigLike(*args, **kwargs)[source]

Bases: Protocol

Structural shape of any object supplying NovelAI client configuration.

token: str | None
username: str | None
password: str | None
image_base_url: str
account_base_url: str
timeout: float
vibe_cache_entries: int
novelai_image_mcp.nai.service.create_novelai_client(config, *, http_client=None)[source]

Create a complete client from a configuration object.

Accepts either a token or a complete username/password pair. Pass a shared http_client when the caller (e.g. the MCP lifespan) wants connection pooling across requests; otherwise the client owns a private session.

Parameters:
Return type:

NovelAIClient

See also