ClassMarker MCP by usefulapi

Read ClassMarker groups, links, exams and recent results; manage question bank and access codes.

Should I use this

Quality & Safety

A
Description quality
100%
Schema completeness
89%
Naming quality
71%
Poisoning risk
100%
Permission match
100%
Protocol compliance
100%

Findings (7)

  • LOWTool 'classmarker_list_groups_links_exams' name length outside 3-30 rangein classmarker_list_groups_links_exams
  • LOWTool 'classmarker_recent_group_results' name length outside 3-30 rangein classmarker_recent_group_results
  • LOWTool 'classmarker_recent_link_results' name length outside 3-30 rangein classmarker_recent_link_results
  • LOWTool 'classmarker_recent_group_exam_results' name length outside 3-30 rangein classmarker_recent_group_exam_results
  • LOWTool 'classmarker_recent_link_exam_results' name length outside 3-30 rangein classmarker_recent_link_exam_results
  • LOWTool 'classmarker_create_parent_category' name length outside 3-30 rangein classmarker_create_parent_category
  • LOWTool 'classmarker_update_parent_category' name length outside 3-30 rangein classmarker_update_parent_category

Based on automated analysis of tool definitions and protocol compliance.

Context Cost

~4,002Tokens (tool definitions)
~2.0 KBTypical response size
Significant attention impact (3.13% of 128k context)

This is the approximate number of tokens consumed each time the server's tools are loaded into a model's context. Higher counts reduce the attention available for other tasks.

Install

One-Click Install

Add this to your `claude_desktop_config.json` file:

{
  "mcpServers": {
    "classmarker": {
      "url": "https://classmarker.usefulapi.io/mcp"
    }
  }
}

Remote endpoints

https://classmarker.usefulapi.io/mcpstreamable-http

What it can do

Tool inventory

Tools (15)

🟢 Read-only🟡 Write🔴 Delete⚪ Unknown
🟢classmarker_list_groups_links_exams

List the groups, links and exams (tests) this API key can access, with the ids the other tools need (group_id, link_id, link_url_id, test_id, and access_list_id for links with an access-code list). Good first call. Counts as one of ClassMarker's 30 requests per hour per API key. API: GET /v1.json.

Input Schema

{
  "type": "object",
  "properties": {},
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🟢classmarker_recent_group_results(finished_after_timestamp, limit, include_monitor_events)

Recent finished test results taken in the key's groups (all groups, all exams), oldest first, PAGED by finish time: test-taker name, email, score, percentage, pass/fail, timing, certificate. Contains personal data: use small pages. Max look-back 3 months. Counts as one of ClassMarker's 30 requests per hour per API key. API: GET /v1/groups/recent_results.json.

Input Schema

{
  "type": "object",
  "properties": {
    "finished_after_timestamp": {
      "description": "UNIX time in SECONDS: only results finished after this are returned (oldest first). Default: 14 days ago. Maximum look-back is 3 months. To page, pass next_finished_after_timestamp from the previous reply.",
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 9007199254740991
    },
    "limit": {
      "description": "Results per request, 1-200 (default 25; ClassMarker's own default is 200).",
      "type": "integer",
      "minimum": 1,
      "maximum": 200
    },
    "include_monitor_events": {
      "description": "Include each result's detailed monitor_events.events list (default false: only the counts).",
      "type": "boolean"
    }
  },
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🟢classmarker_recent_link_results(finished_after_timestamp, limit, include_monitor_events)

Recent finished test results taken through the key's links (all links, all exams), oldest first, PAGED by finish time: test-taker name, email, score, pass/fail, timing, access code, extra tracking fields, IP address, certificate. Contains personal data: use small pages. Max look-back 3 months. Counts as one of ClassMarker's 30 requests per hour per API key. API: GET /v1/links/recent_results.json.

Input Schema

{
  "type": "object",
  "properties": {
    "finished_after_timestamp": {
      "description": "UNIX time in SECONDS: only results finished after this are returned (oldest first). Default: 14 days ago. Maximum look-back is 3 months. To page, pass next_finished_after_timestamp from the previous reply.",
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 9007199254740991
    },
    "limit": {
      "description": "Results per request, 1-200 (default 25; ClassMarker's own default is 200).",
      "type": "integer",
      "minimum": 1,
      "maximum": 200
    },
    "include_monitor_events": {
      "description": "Include each result's detailed monitor_events.events list (default false: only the counts).",
      "type": "boolean"
    }
  },
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🟢classmarker_recent_group_exam_results(group_id, test_id, finished_after_timestamp, limit, include_monitor_events)

Recent finished results for ONE exam in ONE group (ids from classmarker_list_groups_links_exams), oldest first, PAGED by finish time. Contains personal data: use small pages. Counts as one of ClassMarker's 30 requests per hour per API key. API: GET /v1/groups/{group_id}/tests/{test_id}/recent_results.json.

Input Schema

{
  "type": "object",
  "properties": {
    "group_id": {
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 9007199254740991,
      "description": "The group id."
    },
    "test_id": {
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 9007199254740991,
      "description": "The exam (test) id."
    },
    "finished_after_timestamp": {
      "description": "UNIX time in SECONDS: only results finished after this are returned (oldest first). Default: 14 days ago. Maximum look-back is 3 months. To page, pass next_finished_after_timestamp from the previous reply.",
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 9007199254740991
    },
    "limit": {
      "description": "Results per request, 1-200 (default 25; ClassMarker's own default is 200).",
      "type": "integer",
      "minimum": 1,
      "maximum": 200
    },
    "include_monitor_events": {
      "description": "Include each result's detailed monitor_events.events list (default false: only the counts).",
      "type": "boolean"
    }
  },
  "required": [
    "group_id",
    "test_id"
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🟢classmarker_recent_link_exam_results(link_id, test_id, finished_after_timestamp, limit, include_monitor_events)

Recent finished results for the exam of ONE link (ids from classmarker_list_groups_links_exams), oldest first, PAGED by finish time. Contains personal data: use small pages. Counts as one of ClassMarker's 30 requests per hour per API key. API: GET /v1/links/{link_id}/tests/{test_id}/recent_results.json.

Input Schema

{
  "type": "object",
  "properties": {
    "link_id": {
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 9007199254740991,
      "description": "The link id."
    },
    "test_id": {
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 9007199254740991,
      "description": "The exam (test) id."
    },
    "finished_after_timestamp": {
      "description": "UNIX time in SECONDS: only results finished after this are returned (oldest first). Default: 14 days ago. Maximum look-back is 3 months. To page, pass next_finished_after_timestamp from the previous reply.",
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 9007199254740991
    },
    "limit": {
      "description": "Results per request, 1-200 (default 25; ClassMarker's own default is 200).",
      "type": "integer",
      "minimum": 1,
      "maximum": 200
    },
    "include_monitor_events": {
      "description": "Include each result's detailed monitor_events.events list (default false: only the counts).",
      "type": "boolean"
    }
  },
  "required": [
    "link_id",
    "test_id"
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🟢classmarker_list_categories

List the question-bank categories with their parent categories and ids (needed for creating and updating questions). Counts as one of ClassMarker's 30 requests per hour per API key. API: GET /v1/categories.json.

Input Schema

{
  "type": "object",
  "properties": {},
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🟢classmarker_list_questions(page)

List the questions of the question bank, 200 per page (page 1, 2, ...): question text, type, category, points, options, correct options, status. A full page means more may follow, so ask for the next page. Counts as one of ClassMarker's 30 requests per hour per API key. API: GET /v1/questions.json?page=N.

Input Schema

{
  "type": "object",
  "properties": {
    "page": {
      "description": "Page number, 1-based (default 1).",
      "type": "integer",
      "minimum": 1,
      "maximum": 10000
    }
  },
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🟢classmarker_get_question(question_id)

Get one question-bank question by id (ids from classmarker_list_questions). Counts as one of ClassMarker's 30 requests per hour per API key. API: GET /v1/questions/{question_id}.json.

Input Schema

{
  "type": "object",
  "properties": {
    "question_id": {
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 9007199254740991,
      "description": "The question id."
    }
  },
  "required": [
    "question_id"
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🟡classmarker_add_access_codes(access_list_id, codes)

WRITE: add access codes (1-100 per call, up to 255 characters each; a list holds at most 20,000) to a link's access-code list, so those people can start the exam. The access_list_id comes from classmarker_list_groups_links_exams (links[].access_list_id). Only adds; removing codes is not offered. Does not count against the 30 requests per hour limit. API: POST /v1/accesslists/{access_list_id}.json.

Input Schema

{
  "type": "object",
  "properties": {
    "access_list_id": {
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 9007199254740991,
      "description": "The access list id (links[].access_list_id)."
    },
    "codes": {
      "minItems": 1,
      "maxItems": 100,
      "type": "array",
      "items": {
        "type": "string",
        "minLength": 1,
        "maxLength": 255
      },
      "description": "1-100 access codes to add."
    }
  },
  "required": [
    "access_list_id",
    "codes"
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🟡classmarker_create_parent_category(parent_category_name)

WRITE: create a new top-level question category. Returns its parent_category_id. Counts as one of ClassMarker's 30 requests per hour per API key. API: POST /v1/categories/parent_category.json.

Input Schema

{
  "type": "object",
  "properties": {
    "parent_category_name": {
      "type": "string",
      "minLength": 1,
      "maxLength": 255,
      "description": "Name of the new parent category."
    }
  },
  "required": [
    "parent_category_name"
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🔴classmarker_update_parent_category(parent_category_id, parent_category_name)

WRITE: rename an existing parent category (overwrites its name). Counts as one of ClassMarker's 30 requests per hour per API key. API: PUT /v1/categories/parent_category/{parent_category_id}.json.

Input Schema

{
  "type": "object",
  "properties": {
    "parent_category_id": {
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 9007199254740991,
      "description": "The parent category id (from classmarker_list_categories)."
    },
    "parent_category_name": {
      "type": "string",
      "minLength": 1,
      "maxLength": 255,
      "description": "The new name."
    }
  },
  "required": [
    "parent_category_id",
    "parent_category_name"
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🟡classmarker_create_category(category_name, parent_category_id)

WRITE: create a question category under a parent category. Returns its category_id. Counts as one of ClassMarker's 30 requests per hour per API key. API: POST /v1/categories/category.json.

Input Schema

{
  "type": "object",
  "properties": {
    "category_name": {
      "type": "string",
      "minLength": 1,
      "maxLength": 255,
      "description": "Name of the new category."
    },
    "parent_category_id": {
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 9007199254740991,
      "description": "The parent category id (from classmarker_list_categories)."
    }
  },
  "required": [
    "category_name",
    "parent_category_id"
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🔴classmarker_update_category(category_id, category_name, parent_category_id)

WRITE: rename a category and/or move it to another parent (overwrites both fields: send the name and parent_category_id you want it to have). Counts as one of ClassMarker's 30 requests per hour per API key. API: PUT /v1/categories/category/{category_id}.json.

Input Schema

{
  "type": "object",
  "properties": {
    "category_id": {
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 9007199254740991,
      "description": "The category id (from classmarker_list_categories)."
    },
    "category_name": {
      "type": "string",
      "minLength": 1,
      "maxLength": 255,
      "description": "The category's name (new or unchanged)."
    },
    "parent_category_id": {
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 9007199254740991,
      "description": "The parent category id (new or unchanged)."
    }
  },
  "required": [
    "category_id",
    "category_name",
    "parent_category_id"
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🟡classmarker_create_question(question_type, question, category_id, points, options, ...)

WRITE: add a new question to the question bank. Only multiplechoice, multipleresponse, truefalse and essay can be created. Returns the new question_id. For truefalse, give only correct_options ["A"] (True) or ["B"] (False). Counts as one of ClassMarker's 30 requests per hour per API key. API: POST /v1/questions.json.

Input Schema

{
  "type": "object",
  "properties": {
    "question_type": {
      "type": "string",
      "enum": [
        "multiplechoice",
        "multipleresponse",
        "truefalse",
        "essay"
      ],
      "description": "multiplechoice (one correct option), multipleresponse (one or more), truefalse, or essay (graded by hand). Free text, grammar and matching cannot be written."
    },
    "question": {
      "type": "string",
      "minLength": 1,
      "maxLength": 10000,
      "description": "The question text."
    },
    "category_id": {
      "description": "Category id (from classmarker_list_categories).",
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 9007199254740991
    },
    "points": {
      "description": "Points for a correct answer (for an essay: the maximum score).",
      "type": "number",
      "minimum": 0,
      "maximum": 1000
    },
    "options": {
      "description": "Answer options keyed by letter A-J (up to 10), e.g. {\"A\": \"Apply oil\", \"B\": \"Soak in water\"}. Needed for multiplechoice and multipleresponse; not allowed for truefalse and essay.",
      "type": "object",
      "propertyNames": {
        "type": "string"
      },
      "additionalProperties": {
        "type": "string",
        "minLength": 1,
        "maxLength": 5000
      }
    },
    "correct_options": {
      "description": "Letters of the correct options, e.g. [\"C\"]. multiplechoice: exactly one; multipleresponse: one or more; truefalse: [\"A\"] (True) or [\"B\"] (False); not allowed for essay.",
      "type": "array",
      "items": {
        "type": "string"
      }
    },
    "random_answers": {
      "description": "Shuffle the order of the options for each test-taker (multiplechoice / multipleresponse).",
      "type": "boolean"
    },
    "grade_style": {
      "description": "multipleresponse only: partial credit with or without deduction, or off (all-or-nothing).",
      "type": "string",
      "enum": [
        "partial_with_deduction",
        "partial_without_deduction",
        "off"
      ]
    },
    "correct_feedback": {
      "description": "Feedback shown for a correct answer.",
      "type": "string",
      "maxLength": 5000
    },
    "incorrect_feedback": {
      "description": "Feedback shown for an incorrect answer.",
      "type": "string",
      "maxLength": 5000
    }
  },
  "required": [
    "question_type",
    "question"
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🔴classmarker_update_question(question_id, question_type, question, category_id, points, ...)

WRITE (overwrites): replace an existing question-bank question. Send the COMPLETE question (type, text, options, correct options, points, feedback), not only the changed fields; read it first with classmarker_get_question. Only multiplechoice, multipleresponse, truefalse and essay questions can be updated. Counts as one of ClassMarker's 30 requests per hour per API key. API: PUT /v1/questions/{question_id}.json.

Input Schema

{
  "type": "object",
  "properties": {
    "question_id": {
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 9007199254740991,
      "description": "The question id (from classmarker_list_questions)."
    },
    "question_type": {
      "type": "string",
      "enum": [
        "multiplechoice",
        "multipleresponse",
        "truefalse",
        "essay"
      ],
      "description": "multiplechoice (one correct option), multipleresponse (one or more), truefalse, or essay (graded by hand). Free text, grammar and matching cannot be written."
    },
    "question": {
      "type": "string",
      "minLength": 1,
      "maxLength": 10000,
      "description": "The question text."
    },
    "category_id": {
      "description": "Category id (from classmarker_list_categories).",
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 9007199254740991
    },
    "points": {
      "description": "Points for a correct answer (for an essay: the maximum score).",
      "type": "number",
      "minimum": 0,
      "maximum": 1000
    },
    "options": {
      "description": "Answer options keyed by letter A-J (up to 10), e.g. {\"A\": \"Apply oil\", \"B\": \"Soak in water\"}. Needed for multiplechoice and multipleresponse; not allowed for truefalse and essay.",
      "type": "object",
      "propertyNames": {
        "type": "string"
      },
      "additionalProperties": {
        "type": "string",
        "minLength": 1,
        "maxLength": 5000
      }
    },
    "correct_options": {
      "description": "Letters of the correct options, e.g. [\"C\"]. multiplechoice: exactly one; multipleresponse: one or more; truefalse: [\"A\"] (True) or [\"B\"] (False); not allowed for essay.",
      "type": "array",
      "items": {
        "type": "string"
      }
    },
    "random_answers": {
      "description": "Shuffle the order of the options for each test-taker (multiplechoice / multipleresponse).",
      "type": "boolean"
    },
    "grade_style": {
      "description": "multipleresponse only: partial credit with or without deduction, or off (all-or-nothing).",
      "type": "string",
      "enum": [
        "partial_with_deduction",
        "partial_without_deduction",
        "off"
      ]
    },
    "correct_feedback": {
      "description": "Feedback shown for a correct answer.",
      "type": "string",
      "maxLength": 5000
    },
    "incorrect_feedback": {
      "description": "Feedback shown for an incorrect answer.",
      "type": "string",
      "maxLength": 5000
    }
  },
  "required": [
    "question_id",
    "question_type",
    "question"
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}

Community

Rate this Server

Evidence

Recent observations

verifiedversion not recorded15 tools