Skip to main content
Glama

WaniKani MCP Server

by jackedney
models.py7.31 kB
from datetime import UTC, datetime from enum import Enum from typing import Any from sqlmodel import JSON, Column, Field, Relationship, SQLModel class SubjectType(str, Enum): RADICAL = "radical" KANJI = "kanji" VOCABULARY = "vocabulary" KANA_VOCABULARY = "kana_vocabulary" class SyncStatus(str, Enum): SUCCESS = "success" ERROR = "error" IN_PROGRESS = "in_progress" class SyncType(str, Enum): FULL = "full" INCREMENTAL = "incremental" MANUAL = "manual" class User(SQLModel, table=True): id: int | None = Field(default=None, primary_key=True) wanikani_api_key: str = Field(unique=True, index=True) mcp_api_key: str = Field(unique=True, index=True) username: str = Field(index=True) level: int = Field(index=True) profile_url: str | None = None started_at: datetime | None = None subscription_active: bool = Field(default=False) subscription_type: str | None = None subscription_max_level_granted: int | None = None subscription_period_ends_at: datetime | None = None created_at: datetime = Field(default_factory=lambda: datetime.now(UTC)) last_sync: datetime | None = None assignments: list["Assignment"] = Relationship(back_populates="user") reviews: list["Review"] = Relationship(back_populates="user") review_stats: list["ReviewStatistic"] = Relationship(back_populates="user") level_progressions: list["LevelProgression"] = Relationship(back_populates="user") study_materials: list["StudyMaterial"] = Relationship(back_populates="user") sync_logs: list["SyncLog"] = Relationship(back_populates="user") class Subject(SQLModel, table=True): id: int = Field(primary_key=True) object_type: SubjectType = Field(index=True) level: int = Field(index=True) slug: str = Field(index=True) characters: str | None = None meanings: list[dict[str, Any]] = Field(sa_column=Column(JSON)) readings: list[dict[str, Any]] | None = Field(default=None, sa_column=Column(JSON)) component_subject_ids: list[int] | None = Field( default=None, sa_column=Column(JSON) ) amalgamation_subject_ids: list[int] | None = Field( default=None, sa_column=Column(JSON) ) document_url: str hidden_at: datetime | None = None created_at: datetime = Field(default_factory=lambda: datetime.now(UTC)) data_updated_at: datetime | None = None assignments: list["Assignment"] = Relationship(back_populates="subject") reviews: list["Review"] = Relationship(back_populates="subject") review_stats: list["ReviewStatistic"] = Relationship(back_populates="subject") study_materials: list["StudyMaterial"] = Relationship(back_populates="subject") class Assignment(SQLModel, table=True): id: int = Field(primary_key=True) user_id: int = Field(foreign_key="user.id", index=True) subject_id: int = Field(foreign_key="subject.id", index=True) subject_type: SubjectType srs_stage: int = Field(index=True) unlocked_at: datetime | None = None started_at: datetime | None = None passed_at: datetime | None = None burned_at: datetime | None = None available_at: datetime | None = Field(default=None, index=True) resurrected_at: datetime | None = None hidden: bool = Field(default=False) created_at: datetime = Field(default_factory=lambda: datetime.now(UTC)) data_updated_at: datetime | None = None user: User = Relationship(back_populates="assignments") subject: Subject = Relationship(back_populates="assignments") class Review(SQLModel, table=True): id: int = Field(primary_key=True) user_id: int = Field(foreign_key="user.id", index=True) assignment_id: int = Field(index=True) subject_id: int = Field(foreign_key="subject.id", index=True) starting_srs_stage: int ending_srs_stage: int incorrect_meaning_answers: int = Field(default=0) incorrect_reading_answers: int = Field(default=0) created_at: datetime = Field(default_factory=lambda: datetime.now(UTC)) data_updated_at: datetime | None = None user: User = Relationship(back_populates="reviews") subject: Subject = Relationship(back_populates="reviews") class ReviewStatistic(SQLModel, table=True): id: int = Field(primary_key=True) user_id: int = Field(foreign_key="user.id", index=True) subject_id: int = Field(foreign_key="subject.id", index=True) subject_type: SubjectType meaning_correct: int = Field(default=0) meaning_incorrect: int = Field(default=0) meaning_max_streak: int = Field(default=0) meaning_current_streak: int = Field(default=0) reading_correct: int = Field(default=0) reading_incorrect: int = Field(default=0) reading_max_streak: int = Field(default=0) reading_current_streak: int = Field(default=0) percentage_correct: int = Field(default=0) hidden: bool = Field(default=False) created_at: datetime = Field(default_factory=lambda: datetime.now(UTC)) data_updated_at: datetime | None = None user: User = Relationship(back_populates="review_stats") subject: Subject = Relationship(back_populates="review_stats") class SrsStage(SQLModel, table=True): id: int = Field(primary_key=True) position: int = Field(unique=True, index=True) meaning_correct: int meaning_incorrect: int reading_correct: int reading_incorrect: int interval: int interval_unit: str # milliseconds, seconds, minutes, hours, days, weeks class LevelProgression(SQLModel, table=True): id: int = Field(primary_key=True) user_id: int = Field(foreign_key="user.id", index=True) level: int = Field(index=True) unlocked_at: datetime | None = None started_at: datetime | None = None passed_at: datetime | None = None completed_at: datetime | None = None abandoned_at: datetime | None = None created_at: datetime = Field(default_factory=lambda: datetime.now(UTC)) data_updated_at: datetime | None = None user: User = Relationship(back_populates="level_progressions") class StudyMaterial(SQLModel, table=True): id: int = Field(primary_key=True) user_id: int = Field(foreign_key="user.id", index=True) subject_id: int = Field(foreign_key="subject.id", index=True) subject_type: SubjectType meaning_note: str | None = None reading_note: str | None = None meaning_synonyms: list[str] = Field(default_factory=list, sa_column=Column(JSON)) hidden: bool = Field(default=False) created_at: datetime = Field(default_factory=lambda: datetime.now(UTC)) data_updated_at: datetime | None = None user: User = Relationship(back_populates="study_materials") subject: Subject = Relationship(back_populates="study_materials") class VoiceActor(SQLModel, table=True): id: int = Field(primary_key=True) name: str description: str gender: str class SyncLog(SQLModel, table=True): id: int | None = Field(default=None, primary_key=True) user_id: int = Field(foreign_key="user.id", index=True) sync_type: SyncType status: SyncStatus records_updated: int = 0 error_message: str | None = None started_at: datetime = Field(default_factory=lambda: datetime.now(UTC)) completed_at: datetime | None = None user: User = Relationship(back_populates="sync_logs")

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/jackedney/wanikani-mcp'

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