Question Bank MCP Server
README.md
# Question Bank MCP Server
An MCP server for managing K-12 assessment question banks with IRT metadata. Build, organize, and search test questions with full Bloom's taxonomy classification, difficulty calibration, and topic tagging — all through natural language with Claude.



## What is MCP?
[Model Context Protocol](https://modelcontextprotocol.io) (MCP) is an open standard that lets AI assistants like Claude connect to external tools and data sources. This server gives Claude the ability to create, manage, and query question banks directly — no copy-pasting or manual data entry.
## Features
- **Question CRUD** — Create, read, update, and delete questions with full metadata
- **Question types** — Multiple choice, true/false, short answer, and essay
- **Bloom's taxonomy** — Classify questions across all 6 cognitive levels (remember through create)
- **Difficulty calibration** — Continuous 0.0–1.0 scale with easy/medium/hard bucketing
- **IRT metadata** — `discrimination_index`, `times_used`, `times_correct`, `avg_time_seconds`
- **Topic hierarchy** — Organize questions into nested topics within banks
- **Flexible tagging** — Tag questions with arbitrary labels for cross-cutting categorization
- **Search and filter** — Query by type, difficulty range, Bloom's level, topic, tags, status, or free text
- **Bulk activation** — Move multiple questions from draft to active in one call
- **AI suggestions** — Get question ideas for a topic at specified difficulty and Bloom's levels
- **Bank statistics** — Detailed breakdowns by type, difficulty, Bloom's level, and topic
## Quick Start
### 1. Clone and install
```bash
git clone https://github.com/woodstocksoftware/question-bank-mcp.git
cd question-bank-mcp
python3.12 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
```
### 2. Configure Claude Desktop
Add to `~/Library/Application Support/Claude/claude_desktop_config.json`:
```json
{
"mcpServers": {
"question-bank": {
"command": "/path/to/question-bank-mcp/venv/bin/python",
"args": ["/path/to/question-bank-mcp/run_server.py"]
}
}
}
```
Then restart Claude Desktop.
### 3. Configure Claude Code
```bash
claude mcp add question-bank /path/to/question-bank-mcp/venv/bin/python /path/to/question-bank-mcp/run_server.py
```
### 4. Start using it
Ask Claude things like:
> "Create a question bank for AP Biology"
>
> "Add a topic for Cellular Respiration"
>
> "Create a multiple choice question about the Krebs cycle at the Analyze level"
>
> "Show me all hard questions tagged as 'midterm'"
>
> "What are the statistics for my question bank?"
## Tool Reference
### Question Bank Tools
#### `create_question_bank`
Create a new question bank for a course or subject area.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `name` | string | yes | Name of the question bank |
| `subject` | string | yes | Subject area (e.g., "Biology", "Algebra") |
| `description` | string | no | Description of the bank |
| `grade_level` | string | no | Target grade level (e.g., "9-12", "AP") |
#### `list_question_banks`
List all question banks with their question and topic counts. No parameters.
#### `get_bank_statistics`
Get detailed statistics for a question bank, including breakdowns by question type, difficulty bucket, Bloom's level, and topic.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `bank_id` | string | yes | The question bank ID |
### Topic Tools
#### `create_topic`
Add a topic to organize questions within a bank. Supports hierarchical nesting via `parent_topic_id`.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `bank_id` | string | yes | The question bank ID |
| `name` | string | yes | Topic name |
| `description` | string | no | Topic description |
| `parent_topic_id` | string | no | Parent topic ID for nesting |
#### `list_topics`
List all topics in a question bank with question counts.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `bank_id` | string | yes | The question bank ID |
### Question Tools
#### `create_question`
Create a new question with full metadata. Questions start in `draft` status.
| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `bank_id` | string | yes | — | The question bank ID |
| `question_type` | string | yes | — | `multiple_choice`, `true_false`, `short_answer`, or `essay` |
| `stem` | string | yes | — | The question text |
| `correct_answer` | string | yes | — | Correct answer or rubric |
| `options` | list | no | — | Answer choices (for multiple choice) |
| `explanation` | string | no | — | Why the answer is correct |
| `difficulty` | float | no | `0.5` | 0.0 (easy) to 1.0 (hard) |
| `bloom_level` | string | no | — | Bloom's taxonomy level |
| `estimated_time_seconds` | int | no | `60` | Expected time to answer |
| `points` | int | no | `1` | Point value |
| `topic_ids` | list | no | — | Topic IDs to link |
| `tags` | list | no | — | Categorization tags |
#### `get_question`
Retrieve a question by ID with all metadata.
| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `question_id` | string | yes | — | The question ID |
| `show_answer` | bool | no | `true` | Whether to include the answer |
#### `update_question`
Update any field on an existing question, including changing its status.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `question_id` | string | yes | The question ID |
| *(any question field)* | — | no | Fields to update |
#### `delete_question`
Permanently delete a question.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `question_id` | string | yes | The question ID |
#### `search_questions`
Search and filter questions across banks with multiple criteria.
| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `bank_id` | string | no | — | Filter by bank |
| `topic_id` | string | no | — | Filter by topic |
| `question_type` | string | no | — | Filter by type |
| `bloom_level` | string | no | — | Filter by Bloom's level |
| `difficulty_min` | float | no | — | Minimum difficulty |
| `difficulty_max` | float | no | — | Maximum difficulty |
| `status` | string | no | — | `draft`, `active`, or `archived` |
| `tags` | list | no | — | Filter by tags (any match) |
| `search_text` | string | no | — | Text search in stem and explanation |
| `limit` | int | no | `20` | Maximum results |
#### `activate_questions`
Bulk-activate questions, moving them from `draft` to `active` status.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `question_ids` | list | yes | List of question IDs to activate |
#### `suggest_questions`
Get AI-friendly suggestions for new questions to create, based on topic and constraints.
| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `bank_id` | string | yes | — | The question bank ID |
| `topic` | string | yes | — | Topic or learning objective |
| `count` | int | no | `5` | Number of suggestions |
| `difficulty` | string | no | `"mixed"` | `easy`, `medium`, `hard`, or `mixed` |
| `bloom_levels` | list | no | all | Bloom's levels to target |
## Resources
| URI | Description |
|-----|-------------|
| `questionbank://blooms-taxonomy` | Bloom's Taxonomy reference — 6 levels with action verbs, example questions, and writing tips |
| `questionbank://question-types` | Question type guide — when to use each type, best practices |
## Question Schema
### Fields
| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `id` | string | auto | UUID with `q-` prefix |
| `bank_id` | string | — | Parent question bank |
| `question_type` | enum | — | `multiple_choice`, `true_false`, `short_answer`, `essay` |
| `stem` | string | — | The question text |
| `options` | list | — | Answer choices (multiple choice only) |
| `correct_answer` | string | — | Answer or rubric |
| `explanation` | string | — | Why the answer is correct |
| `difficulty` | float | `0.5` | 0.0 (easy) to 1.0 (hard) |
| `bloom_level` | enum | — | `remember`, `understand`, `apply`, `analyze`, `evaluate`, `create` |
| `estimated_time_seconds` | int | `60` | Expected answer time |
| `points` | int | `1` | Point value |
| `status` | enum | `draft` | `draft`, `active`, `archived` |
| `times_used` | int | `0` | Usage counter |
| `times_correct` | int | `0` | Correct response counter |
| `avg_time_seconds` | float | — | Average response time |
| `discrimination_index` | float | — | IRT discrimination parameter |
| `created_at` | timestamp | now | Creation time |
| `updated_at` | timestamp | now | Last update time |
### Difficulty Buckets
| Bucket | Range | Description |
|--------|-------|-------------|
| Easy | 0.0 – 0.3 | Recall and basic comprehension |
| Medium | 0.3 – 0.7 | Application and analysis |
| Hard | 0.7 – 1.0 | Evaluation and synthesis |
### Bloom's Taxonomy Levels
| Level | Example Verbs |
|-------|---------------|
| Remember | define, list, name, identify, recall |
| Understand | describe, explain, summarize, interpret |
| Apply | solve, use, demonstrate, calculate |
| Analyze | compare, contrast, examine, differentiate |
| Evaluate | evaluate, judge, critique, defend |
| Create | design, construct, develop, formulate |
## Usage Examples
### Build a math question bank
> "Create a question bank called 'Algebra 2' for grades 10-11"
>
> "Add topics for Polynomials, Quadratic Equations, and Exponential Functions"
>
> "Create 3 multiple choice questions about factoring polynomials at the Apply level, difficulty 0.4–0.6"
>
> "Activate all the questions we just created"
### Search by difficulty and Bloom's level
> "Find all hard questions at the Evaluate or Create level"
>
> "Search for questions about quadratics with difficulty above 0.7"
>
> "Show me all draft questions tagged 'final-exam'"
### Get suggestions for gaps
> "What are the statistics for my Algebra 2 bank?"
>
> "Suggest 5 easy Remember-level questions about exponential growth"
>
> "We need more Analyze-level questions — suggest some for Quadratic Equations"
## Architecture
```
┌─────────────────────────────────────────────┐
│ Claude Desktop / Code │
│ (MCP Client) │
└──────────────────┬──────────────────────────┘
│ stdio
┌──────────────────▼──────────────────────────┐
│ run_server.py │
│ └─ src/question_bank/server.py │
│ ├─ 12 tools (@mcp.tool) │
│ ├─ 2 resources (@mcp.resource) │
│ └─ Markdown-formatted responses │
└──────────────────┬──────────────────────────┘
│
┌──────────────────▼──────────────────────────┐
│ src/question_bank/database.py │
│ ├─ question_banks (top-level containers)│
│ ├─ topics (hierarchical) │
│ ├─ questions (content + IRT) │
│ ├─ question_topics (many-to-many) │
│ └─ question_tags (many-to-many) │
└──────────────────┬──────────────────────────┘
│
data/question_bank.db (SQLite)
```
## QTI 3.0 Compatibility
The question schema is designed with [QTI 3.0](https://www.imsglobal.org/question/index.html) compatibility in mind. The data model supports the core fields needed for QTI export (question types, correct answers, options, metadata), but import/export is not yet implemented. This is a planned future enhancement.
## Testing
No automated test suite yet. To verify the database layer works correctly:
```bash
python -m src.question_bank.database
```
To confirm the server starts:
```bash
python run_server.py
```
The server runs on stdio transport, so it will appear to hang (it's waiting for MCP client input). Press `Ctrl+C` to stop.
## Contributing
Contributions are welcome! This project is in early development. Areas that could use help:
- Automated tests (pytest)
- QTI 3.0 import/export
- Additional question types
- CI/CD pipeline
## License
[MIT](LICENSE)
---
Built by [Jim Williams](https://linkedin.com/in/woodstocksoftware) | [GitHub](https://github.com/woodstocksoftware)
This server cannot be deployed
Maintenance
ActivityInactive
ResponsivenessNo issues