Skip to main content
Glama
hinoyayoi

japanese-learning-memory

by hinoyayoi

Japanese Learning Memory MCP

一个可本地运行的个人日语学习知识库 MCP Server。它不是普通词典,而是让 ChatGPT、 Codex 或其他 MCP 客户端维护你的知识点、易混关系、真实错误和多维掌握度。

第一版使用 Python 3.11+、官方 MCP Python SDK 稳定版、标准库 sqlite3 和 stdio transport。数据只保存在本机,不调用第三方大模型 API。

能力概览

六个 MCP Tools:

  • search_items:按表达、读音、中文/日文释义和笔记搜索,支持类型、状态、JLPT 筛选。

  • upsert_item:按 (normalized_expression, item_type) 保守查重并新增或更新。

  • add_relation:建立易混、相似、反义、搭配等关系。

  • record_mistake:追加阅读、听力、口语、写作等真实错误。

  • get_due_reviews:只读获取到期复习及尚未复习的 learning 项目。

  • submit_review:保存复习历史、更新对应掌握度并安排下次复习。

四个 Resources:japanese://profilejapanese://statsjapanese://recent-mistakesjapanese://due-today

三个 Prompts:review_todayanalyze_confusionfinish_speaking_session。 Prompts 只向 MCP 客户端提供工作流指导,Server 自己不会调用任何模型。

Related MCP server: Anki Card Manager (acm)

Windows PowerShell 安装

cd <PROJECT_ROOT>
py -3.12 -m venv .venv
.\.venv\Scripts\Activate.ps1
python -m pip install --upgrade pip
python -m pip install -e ".[dev]"

若执行策略阻止激活虚拟环境,可以不激活,后续把 python 替换为 .\.venv\Scripts\python.exe

官方 SDK 依赖固定为 mcp>=1.27,<2。项目创建时 v2 仍是 release candidate, 官方明确建议生产项目使用稳定 v1.x;升级到 v2 前应按官方迁移指南修改并重新验证。

初始化数据库

python -m japanese_learning_mcp.init_db

初始化是幂等的;Server 启动时也会自动执行相同 migration,不会删除或重建已有数据。 默认数据库为项目中的 data\japanese_learning.db。可用环境变量覆盖:

$env:JAPANESE_LEARNING_MCP_DB = "D:\JapaneseData\my-memory.db"
python -m japanese_learning_mcp.init_db

真实 .db、WAL 和 SHM 文件已被 .gitignore 排除。

隐私与版本控制

个人知识点、错误记录、复习历史和掌握度全部保存在本地 SQLite 数据库中,不属于项目 源码。仓库默认忽略 data/ 中的数据库文件、*.db-wal*.db-shm、虚拟环境和 .env 文件,因此公开源码不会公开个人学习数据。

提交代码前仍建议运行 git status --ignored,确认数据库和本机配置处于 ignored 状态。 请勿把包含真实绝对路径、访问令牌或其他隐私信息的 MCP 客户端配置提交到仓库。

测试与静态检查

python -m pytest -q
python -m ruff check .

测试数据库全部位于 pytest 临时目录,不会污染正式数据。

启动 MCP Server

python -m japanese_learning_mcp.server

也可在安装后运行:

japanese-learning-mcp

stdio 协议占用 stdout,因此应用日志只写 stderr。不要在 Server 进程中添加 print()

MCP 客户端配置

将占位符替换为你机器上的绝对路径:

{
  "mcpServers": {
    "japanese-learning-memory": {
      "command": "<PROJECT_ROOT>\\.venv\\Scripts\\python.exe",
      "args": ["-m", "japanese_learning_mcp.server"],
      "env": {
        "JAPANESE_LEARNING_MCP_DB": "<YOUR_DATA_DIRECTORY>\\japanese_learning.db"
      }
    }
  }
}

若接受默认数据位置,可以删除整个 env 字段。不同客户端的配置文件位置不同,但 commandargsenv 的含义相同。

示例录入与查询流程

在 MCP 客户端中依次调用:

  1. search_items({"query":"見落とす","item_type":"vocabulary"}) 查重。

  2. 若不存在,调用 upsert_item({"item_type":"vocabulary","expression":"見落とす","reading":"みおとす", "meaning_zh":"看漏、忽略","jlpt_level":"N1"})

  3. 口语中想不起该词时,使用返回的 item.id 调用 record_mistake({"activity_type":"speaking","problem_type":"recognition_only", "item_id":"<ITEM_ID>","expected_answer":"見落とす"})

  4. 调用 get_due_reviews({"limit":20}) 获取首次或到期任务。

  5. 作答后调用 submit_review({"item_id":"<ITEM_ID>","review_type":"speaking","score":2})

结构化返回包含 action、最终对象、掌握度和 ISO 8601 格式的 next_due_at,适合客户端 稳定解析。

复习规则

第一版使用透明的固定间隔:

score

含义

下次复习

0

完全不会

10 分钟

1

有印象但答错

1 天

2

提示后想起

3 天

3

正确但明显犹豫

7 天

4

快速正确

14 天

5

能主动、自然使用

30 天

规则集中在 services/review_service.py。单次复习只把对应维度朝该分数的目标值移动 25%;表现下降时以 35% 的保守权重下调。mixed 会更新全部五个维度。一次 score 5 不会直接变成完全掌握。

状态为 learning 且无 review 历史的知识点视为“立即可进行首次复习”。该策略不创建 隐式记录;get_due_reviews 始终是纯查询。已有历史的项目以最近一条 review 的 next_due_at 为准,并用日期和 UUID 保证稳定排序。

数据设计说明

  • 每次连接开启 PRAGMA foreign_keys = ON

  • migration 版本记录在 schema_migrations,当前 schema 版本为 1。

  • normalized_expression 仅执行首尾清理、NFKC Unicode 规范化、删除开头展示用 ~/〜(规范化后也识别 ~)和连续空格合并,不做日语词形还原。

  • 不因读音相同合并不同汉字词。

  • confusable_withsimilar_toopposite_to 是对称关系:数据库只保存一行, 两端 UUID 按字典序规范化;反向添加会返回已有关系。

  • 第一版没有物理删除 Tool;请使用 status="archived" 归档。

手动验证

最简单的自动化 MCP 验证是:

python -m pytest tests\test_mcp.py -q

该测试通过官方 SDK 的内存 transport 完成初始化握手,发现 6/4/3 项能力,并真实调用 upsert_item。也可启动 Server 后用 MCP Inspector 连接 stdio 命令进行交互检查。

当前边界

第一版不包含 Web 前端、Docker、第三方模型 API、语音识别、向量数据库、Anki 同步, 也不负责判断日语内容是否权威。examples 数据表已预留来源与验证状态,但首批六个 核心 Tools 尚未提供例句写入 Tool;LLM 生成内容未来接入时必须保持 llm_generated + unverified

Available Tools

6 tools
add_relationA

Add a validated relation between two existing knowledge items.

ParametersJSON Schema
NameRequiredDescriptionDefault
to_item_idYes
explanationNo
from_item_idYes
relation_typeYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A3.9/5.0
Behavior3/5

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

With no annotations, the description carries the behavioral burden. It discloses that the relation is 'validated' and involves 'existing' items, hinting at validation and prerequisites, but it does not explain what validation entails, failure behavior, or whether duplicate/overwriting relations are allowed. This is minimal but non-trivial context.

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 a single concise sentence with no filler or redundancy. It front-loads the primary action and resource, making it immediately clear what the tool does.

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

Completeness3/5

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

Given the tool has an output schema, return values are covered. However, for a mutation tool with no annotations, the description lacks guidance on when to use it, validation failure behavior, and whether relations can be updated or duplicated. It is adequate but not thorough for a tool with four parameters and no structured annotations.

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

Parameters3/5

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

The schema has zero description coverage, so the description must compensate. It maps 'two existing knowledge items' to from_item_id and to_item_id, and 'relation' to relation_type. However, the 'explanation' parameter is not mentioned, and no details on value formats or constraints are provided, leaving a gap.

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 uses a specific verb ('Add') and clearly identifies the resource ('a validated relation between two existing knowledge items'). This clearly distinguishes it from siblings like search_items and submit_review, which serve different purposes.

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

Usage Guidelines4/5

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

The phrase 'between two existing knowledge items' implies a prerequisite that both items must already exist, providing clear usage context. However, it does not explicitly mention when not to use this tool or name alternatives, so it stops short of a 5.

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

get_due_reviewsA

Return due reviews and new learning items; this query never mutates data.

ParametersJSON Schema
NameRequiredDescriptionDefault
as_ofNo
limitNo
item_typeNo
review_typeNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A3.5/5.0
Behavior4/5

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

With no annotations, the description carries the burden of behavioral disclosure. It explicitly states 'never mutates data', which is a key non-mutating guarantee. This adds valuable context beyond the schema, though it omits other potential behaviors like pagination.

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?

Two sentences, front-loaded with the main purpose, followed by a behavior note. Every word earns its place with no unnecessary content.

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?

For a tool with 4 optional parameters, no annotations, and zero parameter documentation, two sentences are inadequate. The output schema covers return structure, but parameter roles and usage context are missing, leaving the agent under-informed.

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

Parameters2/5

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

Schema description coverage is 0% and the description does not explain any of the four parameters (as_of, limit, item_type, review_type). The mention of 'new learning items' only vaguely hints at item_type/review_type filtering, insufficient for correct parameter use.

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 uses the specific verb 'return' and names the resource 'due reviews and new learning items', clearly distinguishing this read tool from the sibling mutation tools. The read-only note further clarifies its role.

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?

No explicit when-to-use guidance or alternatives are provided. The statement 'this query never mutates data' implies safety but does not tell the agent when to choose this tool over search_items or others.

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

record_mistakeB

Append one learning mistake without deduplicating history.

ParametersJSON Schema
NameRequiredDescriptionDefault
promptNo
sourceNo
item_idNo
explanationNo
occurred_atNo
user_answerNo
problem_typeYes
activity_typeYes
expected_answerNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

B3.3/5.0
Behavior3/5

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

With no annotations, the description carries the full burden. It does disclose a key behavior: appending without deduplicating history, which helps the agent understand duplicates are allowed. However, it omits other important traits like permission requirements, reversibility, or side effects beyond the basic append.

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 a single, front-loaded sentence with no filler words. Every word contributes to the meaning, making it an exemplar of concision.

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?

Given the tool has nine parameters and no annotations, the one-sentence description is insufficient. It lacks practical context on when to record a mistake, what the required fields mean, or any workflow guidance. The presence of an output schema mitigates return-value uncertainty but does not compensate for the missing usage and parameter context.

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

Parameters2/5

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

Schema description coverage is 0%, and the description does not elaborate on any of the nine parameters. It provides only a general sense of 'mistake' without mapping to fields, forcing the agent to rely on parameter names alone, which is insufficient for parameters like activity_type and problem_type.

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 uses a specific verb 'append' and identifies the resource as 'learning mistake,' clearly distinguishing this tool from siblings like search_items or submit_review. The phrase 'without deduplicating history' adds a critical behavioral nuance that sets it apart.

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, nor does it mention any exclusions or prerequisites. It simply states the action without context, leaving the agent to infer usage from the name and sibling list.

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

search_itemsC

Search personal Japanese knowledge items with optional filters.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNo
queryYes
statusNo
item_typeNo
jlpt_levelNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

C2.4/5.0
Behavior2/5

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

Since no annotations are provided, the description carries the full burden of disclosing behavioral traits. 'Search' implies a read-only operation, but the description does not mention result ordering, match behavior (e.g., partial vs. exact), default limits, or any side effects. The phrase 'optional filters' hints at filtering capabilities but does not detail them.

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

Conciseness3/5

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

The description is a single short sentence, which is concise but under-specified. Given the tool has five parameters and no schema descriptions, this brevity sacrifices necessary detail, making it more anemic than appropriately concise.

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 five parameters, no annotations, and a 0% schema coverage, the tool is underspecified. The description does not explain the purpose of each filter, how results are returned (although an output schema exists), or when to use this tool vs. sibling tools. The presence of an output schema mitigates some need for return-value detail, but the overall context remains incomplete.

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 description fails to compensate. It only mentions 'optional filters' without naming any of the actual filter parameters (status, item_type, jlpt_level) or explaining the required 'query' parameter or 'limit'. The function's parameter semantics are almost entirely unsupported.

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

Purpose4/5

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

The description clearly states the tool's action ('Search') and resource ('personal Japanese knowledge items'), making its primary purpose unambiguous. However, it does not explicitly differentiate it from sibling tools like get_due_reviews, which also involves searching/fetching items.

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 offers no guidance on when to use this tool versus alternatives such as get_due_reviews or upsert_item. It only implies usage for searching with filters, without any exclusions or contextual prerequisites.

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

submit_reviewA

Save review history, schedule the next review, and conservatively update mastery.

ParametersJSON Schema
NameRequiredDescriptionDefault
notesNo
scoreYes
item_idYes
error_typeNo
review_typeYes
reviewed_atNo
response_time_msNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A3.5/5.0
Behavior3/5

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

With no annotations, the description discloses that the tool saves history, schedules the next review, and updates mastery, which are key behavioral outcomes. However, it does not disclose potential side effects, required preconditions, or details on how 'conservative' mastery updates are performed.

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 a single sentence, front-loaded with action verbs, and contains no redundant information. It efficiently conveys the tool's purpose without unnecessary length.

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?

Given 7 parameters, no annotations, and 0% schema coverage, the description is too sparse to fully equip an agent to invoke the tool correctly. It lacks parameter guidance, edge-case handling, and integration context with the scheduling algorithm.

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

Parameters2/5

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

Schema coverage is 0% (no parameter descriptions). The description provides high-level context but does not explain the meaning or format of individual parameters like score, review_type, error_type, or response_time_ms. Agents must infer parameter semantics from names alone, which is insufficient for correct invocation.

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 uses specific verbs 'Save,' 'schedule,' and 'update' with clear resources (review history, next review, mastery). It clearly distinguishes from siblings like record_mistake (which likely only logs mistakes) and get_due_reviews (which fetches due items).

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

Usage Guidelines3/5

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

The description implies usage when completing a review, but does not explicitly state when to use this tool versus alternatives like record_mistake or upsert_item. No exclusions or contextual triggers are mentioned, leaving the choice to the agent's interpretation.

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

upsert_itemC

Create or update an exact normalized-expression and item-type match.

ParametersJSON Schema
NameRequiredDescriptionDefault
notesNo
sourceNo
statusNolearning
readingNo
item_typeYes
expressionYes
jlpt_levelNounknown
meaning_jaNo
meaning_zhNo
usage_masteryNo
recall_masteryNo
speaking_masteryNo
listening_masteryNo
recognition_masteryNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

C2.6/5.0
Behavior2/5

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

With no annotations provided, the description must disclose behavioral traits, but it only states that it will create or update based on a match. It does not explain what happens when no match exists, whether multiple matches are possible, idempotency, or any side effects.

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

Conciseness4/5

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

The description is a single concise sentence with no filler. It is appropriately front-loaded, though its brevity borders on under-specification; however, that issue is more relevant to completeness than conciseness.

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?

Given the tool's complexity (14 parameters, no annotations) and the presence of an output schema, the description is still too minimal. It lacks usage context, behavioral details, and parameter semantics, making it insufficient for an agent to reliably select and invoke the tool.

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%, so the description must compensate, but it does not describe any parameters except indirectly implying 'expression' and 'item_type' as matching keys. The other 12 parameters remain unexplained, adding no meaning beyond the schema.

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

Purpose4/5

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

The description clearly states the action ('Create or update') and the matching criteria ('exact normalized-expression and item-type match'), which distinguishes it from sibling tools like search_items and add_relation. However, it does not explicitly name the resource ('item') though it is implied by the tool name.

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 gives no guidance on when to use this tool versus alternatives. It does not mention exclusions, prerequisites, or context. The only usage signal is the name 'upsert_item' and the generic upsert behavior.

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. 6 tool updatesv0.1.0
    • First observedadd_relation
    • First observedget_due_reviews
    • First observedrecord_mistake
    • First observedsearch_items
    • First observedsubmit_review
    • First observedupsert_item

TDQS

A3.5/5.0

Scored across 6 tools

Disambiguation5/5

Each tool has a clearly distinct purpose: searching, upserting, relating, recording mistakes, fetching due reviews, and submitting reviews. No two tools overlap in function, and the descriptions reinforce their unique roles.

Naming Consistency5/5

All tool names follow a consistent verb_noun pattern in snake_case (search_items, upsert_item, add_relation, record_mistake, get_due_reviews, submit_review). The verb is always first and the noun is always the object, creating a predictable and readable API.

Tool Count5/5

With six tools, the server is well-scoped for a Japanese learning memory system. Each tool covers a distinct core operation without unnecessary bloat or thinning, fitting the typical 3-15 tool sweet spot.

Completeness4/5

The server covers the core lifecycle: create/update (upsert_item), read/search (search_items), relations (add_relation), and review scheduling (get_due_reviews, submit_review). A minor gap is the lack of an explicit delete operation, but this is not a fatal omission for a spaced-repetition memory system.

Maintenance

ActivitySlowing
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • F
    license
    A
    quality
    D
    maintenance
    This MCP server connects Claude with Anki, allowing users to create flashcards conversationally and automatically deduplicates, classifies, and uploads them without manual copying and pasting. It runs locally with Ollama for embeddings and classification, ensuring privacy.
    13
    -
  • A
    license
    Not graded
    quality
    B
    maintenance
    A local MCP server for journaling, organizing, and recalling your work. It captures entries as plain markdown files, indexes them for full-text and structured search, and enables querying via natural language.
    1
    MIT