Skip to main content
Glama
doy00

TOEIC Speaking MCP Server

by doy00

๐ŸŽฏ TOEIC Speaking MCP Server

ํ† ์ต ์Šคํ”ผํ‚น ๋งŒ๋Šฅ๋ฌธ์žฅ ์•”๊ธฐ ํ…Œ์ŠคํŠธ๋ฅผ ์œ„ํ•œ MCP ์„œ๋ฒ„์ž…๋‹ˆ๋‹ค. Claude Desktop ์•ฑ๊ณผ ์—ฐ๋™ํ•˜์—ฌ ์Œ์„ฑ์œผ๋กœ ํ† ์ต ์Šคํ”ผํ‚น ๋ฌธ์žฅ์„ ํ•™์Šตํ•˜๊ณ  ์ฆ‰์‹œ ํ”ผ๋“œ๋ฐฑ์„ ๋ฐ›์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ถœ์ฒ˜: ์œ ํŠœ๋ธŒ ์‹œ๊ณ„ํ† ๋ผ์ œ๋‹ˆ์Œค


๐Ÿ“– ๋ชฉ์ฐจ


Related MCP server: mcp-server-pronunciation

โœจ ์ฃผ์š” ํŠน์ง•

  • ๐ŸŽค ์Œ์„ฑ ํ•™์Šต: Claude Desktop ์Œ์„ฑ ์ธ์‹์œผ๋กœ ์ž์—ฐ์Šค๋Ÿฌ์šด ํ•™์Šต

  • ๐Ÿง  ์ ์‘ํ˜• ์ถœ์ œ: mastery_score ๊ธฐ๋ฐ˜ ์ทจ์•ฝ ๋ฌธ์žฅ ์šฐ์„  ์ถœ์ œ

  • โšก ์ฆ‰์‹œ ํ”ผ๋“œ๋ฐฑ: ํ‚ค์›Œ๋“œ ๋งค์นญ ๋ถ„์„์œผ๋กœ ์‹ค์‹œ๊ฐ„ ํ•™์Šต ํšจ๊ณผ ํ™•์ธ

  • ๐Ÿ“Š ์ž๋™ ์ ์ˆ˜ ๊ด€๋ฆฌ: ๋‹ต๋ณ€ ์ •ํ™•๋„์— ๋”ฐ๋ฅธ ์ž๋™ ์ ์ˆ˜ ์—…๋ฐ์ดํŠธ (0-100)

  • ๐Ÿ”’ ํƒ€์ž… ์•ˆ์ •์„ฑ: TypeScript strict ๋ชจ๋“œ + Zod ์Šคํ‚ค๋งˆ ๊ฒ€์ฆ

๐Ÿ—๏ธ ๊ธฐ์ˆ  ์Šคํƒ

  • Framework: NestJS 11 + TypeScript 5 (strict mode)

  • Protocol: Model Context Protocol (MCP) SDK

  • Database: Supabase PostgreSQL

  • Validation: Zod schema validation

  • Architecture: Domain-driven layered architecture

๐Ÿš€ ์„ค์น˜ ๋ฐ ์„ค์ •

1. ์˜์กด์„ฑ ์„ค์น˜

npm install

2. ํ™˜๊ฒฝ ๋ณ€์ˆ˜ ์„ค์ •

.env ํŒŒ์ผ ํ™•์ธ:

SUPABASE_URL=your_supabase_url
SUPABASE_ANON_KEY=your_supabase_anon_key

3. ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜

Supabase SQL Editor์—์„œ migrate.sql ์‹คํ–‰:

-- mastery_score, last_reviewed_at, review_count ์ปฌ๋Ÿผ ์ถ”๊ฐ€
-- ์ธ๋ฑ์Šค ์ƒ์„ฑ

4. ์ƒ˜ํ”Œ ๋ฐ์ดํ„ฐ ์‚ฝ์ž… (์„ ํƒ ์‚ฌํ•ญ)

node seed.js

5. ๋นŒ๋“œ

npm run build

6. Claude Desktop ์„ค์ •

~/Library/Application Support/Claude/claude_desktop_config.json:

{
  "mcpServers": {
    "toeic-speaking": {
      "command": "node",
      "args": ["/์ ˆ๋Œ€/๊ฒฝ๋กœ/dist/main.js"],
      "env": {
        "SUPABASE_URL": "your_url",
        "SUPABASE_ANON_KEY": "your_key"
      }
    }
  }
}

โš ๏ธ ๊ฒฝ๋กœ๋ฅผ ์‹ค์ œ ํ”„๋กœ์ ํŠธ ๊ฒฝ๋กœ๋กœ ์ˆ˜์ • ํ›„ Claude Desktop ์žฌ์‹œ์ž‘


๐Ÿ› ๏ธ MCP ๋„๊ตฌ

1. get_quiz_sentence - ๋ฌธ์ œ ์ถœ์ œ

ํŒŒ๋ผ๋ฏธํ„ฐ:

  • mode (์„ ํƒ): 'weak_first' | 'random' (๊ธฐ๋ณธ: 'weak_first')

  • part (์„ ํƒ): ํŒŒํŠธ ๋ฒˆํ˜ธ ํ•„ํ„ฐ

์‘๋‹ต:

{
  "id": "uuid",
  "sentence_ko": "์ด ์‚ฌ์ง„์€ ๊ณต์›์—์„œ ์ฐํžŒ ์‚ฌ์ง„์ž…๋‹ˆ๋‹ค.",
  "part": 2,
  "current_mastery": 0
}

2. verify_answer - ๋‹ต๋ณ€ ๊ฒ€์ฆ

ํŒŒ๋ผ๋ฏธํ„ฐ (ํ•„์ˆ˜):

  • sentence_id: ๋ฌธ์žฅ ID

  • user_answer: ์‚ฌ์šฉ์ž ๋‹ต๋ณ€ (์˜์–ด ๋ฌธ์žฅ)

์‘๋‹ต:

{
  "success": true,
  "original_sentence": "This is a picture taken at a park.",
  "matched_keywords": ["picture", "taken", "park"],
  "missing_keywords": [],
  "match_rate": "100.0%",
  "score_change": 10,
  "feedback": "Perfect! All keywords matched. Score increased by 10 points."
}

์ ์ˆ˜ ๊ทœ์น™:

๋งค์นญ๋ฅ 

์ ์ˆ˜ ๋ณ€ํ™”

100%

+10

70-99%

+5

50-69%

0

0-49%

-5


๐Ÿ’ฌ ์‚ฌ์šฉ ์˜ˆ์‹œ

๐Ÿ‘ค "ํ† ์ต ์Šคํ”ผํ‚น ์—ฐ์Šต ์‹œ์ž‘ํ• ๊ฒŒ์š”"

๐Ÿค– [get_quiz_sentence ํ˜ธ์ถœ]
   ๋ฌธ์ œ: "์ด ์‚ฌ์ง„์€ ๊ณต์›์—์„œ ์ฐํžŒ ์‚ฌ์ง„์ž…๋‹ˆ๋‹ค."
   (ํ˜„์žฌ ์ˆ™๋ จ๋„: 0์ )

๐Ÿ‘ค [์Œ์„ฑ] "This is a picture taken at a park"

๐Ÿค– [verify_answer ํ˜ธ์ถœ]
   โœ… ์™„๋ฒฝํ•ฉ๋‹ˆ๋‹ค!
   - ํฌํ•จ๋œ ํ‚ค์›Œ๋“œ: picture, taken, park (3/3)
   - ๋งค์นญ๋ฅ : 100.0%
   - ์ ์ˆ˜ ๋ณ€ํ™”: +10์ 

๐Ÿ“ ํ”„๋กœ์ ํŠธ ๊ตฌ์กฐ

src/
โ”œโ”€โ”€ main.ts                    # MCP ์„œ๋ฒ„ ์—”ํŠธ๋ฆฌํฌ์ธํŠธ
โ”œโ”€โ”€ app.module.ts              # ๋ฃจํŠธ ๋ชจ๋“ˆ
โ”œโ”€โ”€ config/
โ”‚   โ””โ”€โ”€ supabase.config.ts     # Supabase DI Provider
โ”œโ”€โ”€ types/
โ”‚   โ””โ”€โ”€ sentence.interface.ts  # TypeScript ์ธํ„ฐํŽ˜์ด์Šค
โ”œโ”€โ”€ mcp/
โ”‚   โ”œโ”€โ”€ mcp.module.ts
โ”‚   โ””โ”€โ”€ mcp.service.ts         # MCP ๋„๊ตฌ ์ •์˜ + Zod ๊ฒ€์ฆ
โ”œโ”€โ”€ quiz/                      # Quiz ๋„๋ฉ”์ธ
โ”‚   โ”œโ”€โ”€ quiz.module.ts
โ”‚   โ”œโ”€โ”€ quiz.service.ts        # ๋ฌธ์ œ ์ถœ์ œ ๋กœ์ง
โ”‚   โ””โ”€โ”€ quiz.repository.ts     # DB ์ฟผ๋ฆฌ
โ””โ”€โ”€ answer/                    # Answer ๋„๋ฉ”์ธ
    โ”œโ”€โ”€ answer.module.ts
    โ”œโ”€โ”€ answer.service.ts      # ํ‚ค์›Œ๋“œ ๋งค์นญ ์•Œ๊ณ ๋ฆฌ์ฆ˜
    โ””โ”€โ”€ answer.repository.ts   # ์ ์ˆ˜ ์—…๋ฐ์ดํŠธ

์•„ํ‚คํ…์ฒ˜:

Claude Desktop (stdio)
    โ†“
MCP Layer (Zod ๊ฒ€์ฆ)
    โ†“
Domain Layer (Quiz/Answer)
    โ†“
Supabase PostgreSQL

๐Ÿ—„๏ธ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์Šคํ‚ค๋งˆ

์ปฌ๋Ÿผ

ํƒ€์ž…

์„ค๋ช…

id

uuid

PK

part

integer

TOEIC ํŒŒํŠธ ๋ฒˆํ˜ธ

sentence_en

text

์˜์–ด ์›๋ฌธ (์ •๋‹ต)

sentence_ko

text

ํ•œ๊ตญ์–ด ๋ฒˆ์—ญ (๋ฌธ์ œ)

keywords

text[]

ํ•ต์‹ฌ ํ‚ค์›Œ๋“œ ๋ฐฐ์—ด

mastery_score

integer

ํ•™์Šต ์ˆ™๋ จ๋„ (0-100)

last_reviewed_at

timestamptz

๋งˆ์ง€๋ง‰ ๋ณต์Šต ์‹œ๊ฐ

review_count

integer

์ด ๋ณต์Šต ํšŸ์ˆ˜

์ธ๋ฑ์Šค:

  • idx_mastery_score: mastery_score

  • idx_part_mastery: (part, mastery_score)


๐Ÿ”ง ํŠธ๋Ÿฌ๋ธ”์ŠˆํŒ…

MCP ์„œ๋ฒ„๊ฐ€ ๋ณด์ด์ง€ ์•Š๋Š” ๊ฒฝ์šฐ

  1. ๋นŒ๋“œ ํ™•์ธ: npm run build

  2. ํŒŒ์ผ ํ™•์ธ: ls dist/main.js

  3. ์ˆ˜๋™ ์‹คํ–‰: node dist/main.js

  4. Claude Desktop ๋กœ๊ทธ ํ™•์ธ: View > Toggle Developer Tools > Console

  5. Claude Desktop ์™„์ „ํžˆ ์žฌ์‹œ์ž‘

๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ ์˜ค๋ฅ˜

  1. claude_desktop_config.json์˜ env ์„น์…˜ ํ™•์ธ

  2. stdio ํ™˜๊ฒฝ์—์„œ๋Š” .env ํŒŒ์ผ ๋Œ€์‹  ์„ค์ • ํŒŒ์ผ์— ํ™˜๊ฒฝ ๋ณ€์ˆ˜ ํ•„์ˆ˜

  3. Supabase ํ”„๋กœ์ ํŠธ ํ™œ์„ฑ ์ƒํƒœ ํ™•์ธ

  4. migrate.sql ์‹คํ–‰ ํ™•์ธ

ํƒ€์ž… ์—๋Ÿฌ

rm -rf node_modules package-lock.json
npm install
npm run build

๐Ÿ› ๏ธ ๊ฐœ๋ฐœ ๋ช…๋ น์–ด

# ๋นŒ๋“œ
npm run build

# ๊ฐœ๋ฐœ ๋ชจ๋“œ
npm run start:dev

# ์‹คํ–‰
npm start

# ์ƒ˜ํ”Œ ๋ฐ์ดํ„ฐ
node seed.js

# ํƒ€์ž… ์ฒดํฌ
npx tsc --noEmit

๐ŸŽ“ ํ•™์Šต ํŒ

  1. ๋งค์ผ 10-15๋ถ„ ๊พธ์ค€ํžˆ ์—ฐ์Šต

  2. weak_first ๋ชจ๋“œ ํ™œ์šฉ์œผ๋กœ ์ทจ์•ฝ ๋ฌธ์žฅ ์ง‘์ค‘ ๊ณต๋žต

  3. ํ‚ค์›Œ๋“œ ์ค‘์‹ฌ ํ•™์Šต (์ „์ฒด ๋ฌธ์žฅ๋ณด๋‹ค ํ•ต์‹ฌ ํ‚ค์›Œ๋“œ ๋จผ์ € ์•”๊ธฐ)

  4. ์Œ์„ฑ ์ž…๋ ฅ ์‚ฌ์šฉ์œผ๋กœ ๋ฐœ์Œ ์—ฐ์Šต ๋ณ‘ํ–‰

  5. ์ ์ˆ˜ 80์  ์ด์ƒ ๋˜๋ฉด ์ž๋™์œผ๋กœ ๋‹ค๋ฅธ ๋ฌธ์žฅ ์ถœ์ œ


๐Ÿš€ ํ–ฅํ›„ ๊ณ„ํš

  • 187๊ฐœ ์ „์ฒด ๋ฌธ์žฅ ๋ฐ์ดํ„ฐ ์ถ”๊ฐ€

  • Part 3, 4, 5 ์ง€์›

  • ํ•™์Šต ํ†ต๊ณ„ ๋Œ€์‹œ๋ณด๋“œ

  • ์‚ฌ์šฉ์ž๋ณ„ ํ•™์Šต ๊ธฐ๋ก

  • ๋ฐœ์Œ ํ‰๊ฐ€ API ์—ฐ๋™


๐Ÿ“š ์ฐธ๊ณ  ์ž๋ฃŒ


๐Ÿ“„ ๋ผ์ด์„ ์Šค

ISC


Version: 1.0.0 | Last Updated: 2026-03-15

Available Tools

2 tools
get_quiz_sentenceB

mastery_score๊ฐ€ ๋‚ฎ์€ ๋ฌธ์žฅ ์šฐ์„ ์œผ๋กœ ํ€ด์ฆˆ ๋ฌธ์ œ๋ฅผ ์ถœ์ œํ•ฉ๋‹ˆ๋‹ค

ParametersJSON Schema
NameRequiredDescriptionDefault
modeNo์ถœ์ œ ๋ชจ๋“œ (๊ธฐ๋ณธ๊ฐ’: weak_first)
partNoํŒŒํŠธ ๋ฒˆํ˜ธ ํ•„ํ„ฐ (์„ ํƒ ์‚ฌํ•ญ)

TDQS

B3.3/5.0
Behavior2/5

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

With no annotations provided, the description carries the full burden of disclosure. It does mention the prioritization behavior (low mastery_score first), but it does not explain what the tool returns (e.g., a single sentence or a list), how many items are generated, or whether any state changes occur. This is a significant gap for a generation tool.

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, efficient sentence that front-loads the primary purpose. Every word earns its place, with no redundant filler.

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?

The tool is relatively simple with two optional parameters and no output schema, so the description is adequate for basic understanding. However, it omits return value details (what exactly the tool returns) and lacks explicit connection to the sibling verify_answer tool, leaving some context incomplete.

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?

Schema description coverage is 100%, with both parameters ('mode' and 'part') already documented in the schema. The description adds no additional meaning beyond the schema, so the baseline score of 3 is appropriate.

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 ('์ถœ์ œ' = generate/select questions), names the resource ('quiz sentence'), and includes a key detail (prioritizing low mastery_score). This clearly distinguishes it from the sibling tool verify_answer, which verifies answers rather than generating questions.

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 guidance is given on when to use this tool versus verify_answer, nor when to choose the 'weak_first' or 'random' modes. The description implies usage for quiz generation but does not provide explicit context or exclusions.

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

verify_answerA

์‚ฌ์šฉ์ž ๋‹ต๋ณ€์„ ๊ฒ€์ฆํ•˜๊ณ  ํ‚ค์›Œ๋“œ ํฌํ•จ ์—ฌ๋ถ€์— ๋”ฐ๋ผ ์ ์ˆ˜๋ฅผ ์—…๋ฐ์ดํŠธํ•ฉ๋‹ˆ๋‹ค

ParametersJSON Schema
NameRequiredDescriptionDefault
sentence_idYes๋ฌธ์žฅ ID
user_answerYes์‚ฌ์šฉ์ž๊ฐ€ ๋งํ•œ ์˜์–ด ๋ฌธ์žฅ

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 carries the full burden of behavioral disclosure. It discloses that the tool updates scores based on keyword inclusion, which is useful context, but it does not explain side effects, irreversibility, permission requirements, or return values. The description gives partial transparency but leaves important gaps.

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 that directly conveys the tool's purpose and core behavior. No wasted words or redundant details.

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?

The tool is relatively simple with two parameters and no output schema, but the description does not mention what the tool returns or what 'updates the score' entails. It provides the core action but lacks context about the response and any prerequisites, leaving the description minimally sufficient rather than complete.

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?

Schema description coverage is 100%, and the description does not add meaningful information beyond the parameter descriptions already present. The baseline of 3 applies because the schema handles parameter semantics adequately.

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 clearly states a specific action: verifying the user's answer and updating the score based on keyword inclusion. It distinguishes the tool from its sibling 'get_quiz_sentence' by focusing on verification and score update rather than retrieval.

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 guidance is provided on when to use this tool versus alternatives. The description implies it is used for answer verification and scoring, but does not state prerequisites, exclusions, or when a different tool would be more appropriate.

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

TDQS

A3.7/5.0
Disambiguation5/5

The two tools have clearly distinct roles: one generates a quiz question, the other validates the user's answer. There is no functional overlap between them.

Naming Consistency5/5

Both tool names follow a consistent verb_noun pattern: 'get_quiz_sentence' and 'verify_answer'. This predictable naming makes the tool set easy to navigate.

Tool Count3/5

With only 2 tools, the server is on the thin side, but the narrow quiz-taking purpose makes this count borderline acceptable. It covers the essential actions without being bloated.

Completeness4/5

The tools form a complete core workflow: retrieve a question and verify a response. Minor gaps exist, such as no explicit score retrieval or session management, but the primary quiz loop is fully covered.

Maintenance

ActivityInactive
ResponsivenessNo issues

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

Related MCP Servers

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/doy00/mcp-toeic-speaking-sentences'

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