DeepMark
Server Details
DeepMark helps teachers deliver rapid, consistent marking with meaningful feedback for every student — in a fraction of the time. What once took a week, now takes one free period.
- Status
- Healthy
- Uptime
- 100.0% over 75 days
- OAuth
- Works in Glama
- Last Tested
- Transport
- Streamable HTTP · MCP 2025-11-25
- URL
TDQS
Scored across 13 tools
Most tools map cleanly to a distinct resource+action (paper_create/paper_confirm/paper_get/paper_list, pupil_get/pupil_list, submission_mark/submission_get). The one fuzzy boundary is markResult_get versus submission_get, both of which return marking outcomes, and ingestion_get versus submission_get, both async polling endpoints for different jobs. Descriptions do clarify these, but the overlap is real enough to cost a point.
The set follows a predictable noun_action pattern (paper_create, pupil_get, submission_mark, results_get) throughout. The only deviations are markResult_get and markScheme_update, which camelCase the compound resource name instead of using underscores. Minor but visible inconsistency.
Thirteen tools covering papers, ingestion jobs, submissions, mark results, mark schemes, questions, pupils and results is well within the healthy 3-15 range. Every tool corresponds to a real step in the create-paper -> mark -> analyse workflow, with no filler.
Core lifecycle (create paper, confirm, mark submission, read results/pupils) is covered, but there are notable gaps: no paper update/delete, no submission list or delete, and markScheme_update exists without any markScheme_get or create, leaving that resource a partial dead end. Question handling is also update-only, with creation implicit in paper_create.
Available Tools
13 toolsingestion_getGet Ingestion Job StateARead-onlyIdempotentInspect
Read the current state of an ingestion job (paper creation or document ingestion). Returns the status plus a derived awaiting gate ('triage' | 'confirmation' | null), whether it is terminal, and the next action to take. Poll this after starting a job: a paper-creation job parks at awaiting_confirmation (then call paper_confirm) — it does NOT run to complete on its own. Stop polling on a terminal status (complete | failed | cancelled) or when an action is required.
| Name | Required | Description | Default |
|---|---|---|---|
| job_id | Yes | ID of the ingestion job to read the current state of. |
Output Schema
| Name | Required | Description |
|---|---|---|
| kind | Yes | The ingestion job kind (paper_bundle, student_batch, source_document, …). |
| error | Yes | Failure detail, when status is failed. |
| job_id | Yes | |
| status | Yes | Raw ingestion status. |
| awaiting | Yes | The gate the job is parked at, or null if none. `start` means it has not been handed to a queue at all and a person must act before it is — polling will never resolve it. |
| terminal | Yes | True once the job will not change on its own. |
| created_at | Yes | ISO-8601 creation timestamp. |
| needs_action | Yes | Human-readable next step for the caller. |
| processed_at | Yes | ISO-8601 completion timestamp, or null if not yet processed. |
| attempt_count | Yes | Processing attempts so far. |
| exam_paper_id | Yes | The minted paper's id, once one exists. |
| triage_summary | Yes | Triage explanation, only while parked at the triage gate. |
| triage_issue_count | Yes | How many triage issues, only while parked at the triage gate. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish readOnly/idempotent/safe-read, and the description goes well beyond them: it discloses the derived `awaiting` gate values ('triage' | 'confirmation' | null), the terminal-state set, and the surprising lifecycle behavior that paper-creation jobs do not self-complete. That is real behavioral context an agent cannot infer from the schema or annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, each doing distinct work: what is returned, the confirmation-park caveat, and the stop condition. Front-loaded with the core action and free of redundant restatement of the title.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return-value documentation is correctly left out, yet the description still surfaces the derived `awaiting` gate and terminal states that drive the calling loop. For a single-parameter polling tool, nothing an agent needs to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and there is a single required parameter, so the schema already fully documents `job_id` as the ID of the ingestion job. The description adds no format, sourcing, or error semantics beyond what the schema states; baseline 3 applies when the schema does the heavy lifting.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: 'Read the current state of an ingestion job', with the scope qualifier '(paper creation or document ingestion)' that ties it to the ingestion job family. This is clearly distinct from siblings like paper_get, results_get, or submission_get, which return domain objects rather than job state.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly says when to call it ('Poll this after starting a job'), when to stop ('on a terminal status (complete | failed | cancelled) or when an action is required'), and names the follow-up sibling (paper_confirm). It also flags the non-obvious case that a paper-creation job parks at awaiting_confirmation rather than running to complete, which is exactly the guidance an agent needs to avoid a polling loop.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
markResult_getGet Mark Result by Answer IDCRead-onlyIdempotentInspect
Retrieve the marking result for a specific answer by its ID
| Name | Required | Description | Default |
|---|---|---|---|
| answer_id | Yes | The unique identifier for the answer to retrieve the marking result for |
Output Schema
| Name | Required | Description |
|---|---|---|
| answer_id | Yes | |
| marked_at | Yes | ISO-8601 timestamp the mark was recorded. |
| mark_points | Yes | Per-mark-point decisions (point_based questions); [] otherwise. |
| mark_scheme | Yes | |
| total_score | Yes | |
| llm_reasoning | Yes | |
| feedback_summary | Yes | |
| max_possible_score | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and a closed-world scope, so the safety profile is covered. The description adds nothing further — no note on what happens for an unmigrated/unmarked answer, authorization needs, or result freshness — so it contributes no behavioral context of its own.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single front-loaded sentence with no wasted words. It is efficient, though its brevity stems partly from omitting useful routing information rather than from disciplined editing.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a one-parameter lookup with an output schema and annotations, the core need is covered and return values need not be explained. The missing piece is disambiguation from the other retrieval siblings, which is the main thing an agent could get wrong here.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The single required parameter is fully documented in the schema (100% coverage), so the description merely restates 'by its ID'. Baseline 3 applies since the schema carries the semantics and the description adds no format or sourcing details.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('Retrieve') and resource ('marking result for a specific answer by its ID'), which is clear and predictable. However, it does not distinguish itself from nearby siblings like results_get or submission_get, so an agent must infer which retrieval tool applies.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no explicit when-to-use guidance and no alternative is named. With siblings such as results_get, submission_get, and submission_mark in the same family, the agent gets no help deciding which one to pick for a given task.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
markScheme_updateUpdate Mark SchemeCIdempotentInspect
Update an existing mark scheme by its ID
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | The unique identifier for the mark scheme to update | |
| content | No | The full mark scheme content text (level descriptors, caps, guidance, etc.) | |
| mark_points | No | Array of mark points | |
| points_total | No | The question's total marks. Stored on the question — a mark scheme is always out of its question's total. | |
| marking_method | No | How to mark: deterministic (MCQ), point_based, or level_of_response |
Output Schema
| Name | Required | Description |
|---|---|---|
| updated | Yes | Names of the fields written by this call. |
| question_id | Yes | |
| points_total | Yes | The question's total marks after the update. |
| mark_scheme_id | Yes | |
| mark_point_count | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare that this is a non-read-only, idempotent, non-destructive mutation, and the description adds only that it updates an existing record by ID. It does not disclose important behavioral details such as whether unspecified fields are preserved, whether content or mark_points are replaced wholesale, or any permission requirements.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single front-loaded sentence with no wasted wording. It is appropriately concise, though its brevity leaves no room for structural guidance on the more complex mark scheme fields.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool has a fully documented schema, annotations covering its safety profile, and an output schema, so the description does not need to explain return values. However, for a five-parameter mutation involving nested mark points, it remains thin on update semantics and is only minimally sufficient.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the input schema already documents all five parameters in detail. The description adds no parameter-specific meaning beyond what the schema provides, making the baseline 3 appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: update an existing mark scheme by ID. It is clear what the tool does, though it does not explicitly distinguish itself from the related question_update sibling.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies that a valid existing ID is required, but it gives no explicit guidance on when to use this tool versus alternatives or what kinds of updates are appropriate. It is essentially a restatement of the action without usage context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
paper_confirmConfirm Exam Paper DraftAIdempotentInspect
Mint the exam paper from a job parked at awaiting_confirmation (created via paper_create). Materialises the ExamPaper, questions, and mark schemes from the extraction draft, synchronously. Optionally override the detected identity (title/subject/board/year); omit to use what extraction detected. Idempotent — confirming an already-committed job returns its paper. Returns the exam_paper_id.
| Name | Required | Description | Default |
|---|---|---|---|
| job_id | Yes | ID of the ingestion job to confirm. Must be parked at awaiting_confirmation (poll ingestion_get first). | |
| metadata | No | Optional identity overrides. Omit to mint the paper with the identity detected during extraction. `total_marks` is always derived from the question marks — never supplied here. |
Output Schema
| Name | Required | Description |
|---|---|---|
| status | Yes | Terminal status of the paper (complete). |
| outcome | Yes | "created" on first confirm, "already committed" on re-confirm. |
| view_with | Yes | The tool to inspect the paper with (paper_get). |
| exam_paper_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare idempotentHint=true and destructiveHint=false, and the description reinforces idempotency with concrete semantics ('confirming an already-committed job returns its paper'). It also discloses that materialisation is synchronous, which is real operational context the annotations cannot express. It stops short of saying what happens to the extraction draft after minting or how a wrong-state job fails.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four tight sentences, front-loaded with the action and precondition, each carrying information. The closing 'Returns the exam_paper_id' is slightly redundant given an output schema exists, but it costs little.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With a rich annotation set, 100% schema coverage and an output schema, the description covers the operation's key facts: prerequisite job state, synchronous materialisation, override/omit behavior, and idempotency. The remaining gap is failure and side-effect behavior — what happens to the draft or the job on success, and what an unsatisfied precondition yields.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents job_id, every override field, the subject enum, and the assessment_date caveat. The description only restates the override group at a high level ('optionally override the detected identity (title/subject/board/year)'); it notably omits assessment_date from that list and adds no formatting detail beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource — mint an ExamPaper from a job at awaiting_confirmation — and names the entities produced (ExamPaper, questions, mark schemes). It also anchors itself against paper_create (the producer of the job) and paper_get (the reader), so an agent can route without opening schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives the precondition (job must be parked at awaiting_confirmation, created via paper_create) and the override rule: supply metadata to override, omit to inherit what extraction detected. It does not explicitly say what to do if the job is not yet parked, or point at a specific alternative for reading a paper instead.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
paper_createCreate Exam Paper from TextAInspect
Create a complete, markable exam paper from pasted text. Provide the question paper text (required) and, if the teacher has one, the mark scheme text — DeepMark extracts it. Omit the mark scheme to have DeepMark generate schemes (lower quality, but the paper is still markable). Send RAW text: do not pre-structure it into questions or author a mark scheme yourself. Extraction runs asynchronously — this returns a job_id. Poll ingestion_get until it reaches awaiting_confirmation, then call paper_confirm to mint the paper. RATE LIMITED: up to 3 papers per 24 hours per account (marking existing papers is unaffected).
| Name | Required | Description | Default |
|---|---|---|---|
| hints | No | Optional cover-identity hints. SOFT grounding for extraction — they steer the model, they do not override the paper text. | |
| stimulus_text | No | Optional source/stimulus material the questions refer to (a passage, dataset, case study). Supplied as extraction context; it is not itself turned into questions. | |
| mark_scheme_text | No | RAW text of the mark scheme, if the teacher has one. Read jointly with the question paper so marks and numbering align. Send raw text, NOT a mark scheme you authored. Omit entirely when there is no mark scheme — DeepMark generates one per question (lower quality than a real scheme, but the paper is still markable). | |
| question_paper_text | Yes | RAW text of the question paper — questions, bracketed marks, section headers, as printed or pasted. Send the source text and let DeepMark extract the questions. Do NOT pre-structure it into questions yourself. |
Output Schema
| Name | Required | Description |
|---|---|---|
| job_id | Yes | |
| status | Yes | The job's initial status (pending). |
| poll_with | Yes | The tool to poll this job with (ingestion_get). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond annotations (which only say it is a non-readonly, non-idempotent, non-destructive write): it discloses asynchronous execution, the returned job_id, the required polling handshake, a hard rate limit of 3 papers per 24 hours, and the quality tradeoff when no mark scheme is supplied. It also clarifies marking existing papers is unaffected by the limit.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads the purpose, then the required input, then the optional path, then the async workflow, then the rate limit — a logical ordering with no wasted sentences. Capitalized RATE LIMITED emphasis highlights the constraint that would most likely cause a failed call.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be described, yet the description still names the key field (job_id) and the follow-up calls. Combined with the rate limit and raw-text requirement, an agent has everything needed to invoke and complete the flow correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so all four parameters including the nested hints object are already documented in the schema. The description reinforces the required/optional split and the 'send raw text' constraint, but adds no syntax, format, or length detail beyond what the schema states.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource — 'Create a complete, markable exam paper from pasted text' — and the scope (extraction from raw text) is unmistakable. It is clearly distinguishable from siblings like paper_confirm, ingestion_get, and paper_get, which are named as separate steps.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives the full workflow explicitly: call this, poll ingestion_get until `awaiting_confirmation`, then call paper_confirm. It also states the conditional path for the mark scheme (supply it if available, omit it to have DeepMark generate one) and the negative instruction not to pre-structure text.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
paper_getGet Exam Paper by IDARead-onlyIdempotentInspect
Retrieve a specific exam paper by its ID with question details
| Name | Required | Description | Default |
|---|---|---|---|
| exam_paper_id | Yes | The ID of the exam paper to retrieve |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | Yes | |
| tier | Yes | |
| year | Yes | |
| title | Yes | |
| subject | Yes | |
| sections | Yes | |
| created_at | Yes | ISO-8601 creation timestamp. |
| created_by | Yes | |
| exam_board | Yes | |
| total_marks | Yes | |
| paper_number | Yes | |
| duration_minutes | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint and a closed world, so the safety profile is covered. The description adds that question details come back in the payload, which is useful context, but says nothing about behavior when the ID is invalid or missing. With annotations carrying the main burden, a 3 is appropriate.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
One short sentence with the key information front-loaded and no wasted clauses. It is close to minimal, though 'with question details' is slightly vague about what is actually returned.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
A simple read tool with one fully documented required parameter, a rich annotation set, and an output schema that handles return-value explanation. Nearly everything an agent needs to call it correctly is present; only error/not-found behavior is unaddressed, which is minor here.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The single parameter has 100% schema description coverage ('The ID of the exam paper to retrieve'), so the schema does the work. The description only restates that lookup is by ID and adds no ID format, source, or validation details, matching the baseline 3 for high coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Retrieve a specific exam paper by its ID') and adds that question details are included, which distinguishes it from a bare list call. It doesn't explicitly contrast with siblings like paper_list or submission_get, so an agent must infer the single-record vs. collection split.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is only implied by 'by its ID' — the agent can infer this is the single-record fetch when an exam_paper_id is known. There is no explicit when-to-use, no mention of when to prefer paper_list or another sibling, and no prerequisite or not-found guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
paper_listList Exam PapersCRead-onlyIdempotentInspect
List all exam papers with optional filtering
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Maximum number of papers to return (pagination page size). | |
| offset | No | Number of papers to skip before returning results (pagination). | |
| subject | No | Filter to a single subject. |
Output Schema
| Name | Required | Description |
|---|---|---|
| limit | Yes | |
| offset | Yes | |
| papers | Yes | |
| has_more | Yes | True when a full page came back — request the next offset. |
| returned | Yes | How many papers this page returned. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint and closed-world, so safety is covered. The description adds nothing beyond that — no mention of default page size behavior, ordering, or what an empty result means.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single front-loaded sentence with no filler. It is efficiently sized, though the brevity borders on under-specification rather than optimal conciseness.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool is a simple read with an output schema and fully documented parameters, so structured data carries most of the burden. The description is technically sufficient to invoke but omits any note on ordering, default behavior or result shape nuances.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% with pagination defaults and a full subject enum documented in the schema. The description's 'optional filtering' merely restates this, adding no syntax or format detail, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('List all exam papers'), clearly distinguishing the read/list operation from paper_get and paper_create. It does not explicitly name or contrast with siblings, which is required for a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Only 'with optional filtering' hints at usage; there is no guidance on when to use this vs paper_get, whether results are paginated by default, or any prerequisites. An agent must infer the selection context entirely.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
pupil_getGet PupilARead-onlyIdempotentInspect
One pupil in one subject: every assessment across all years with its date, school year, grade and percentage; the change since their previous assessment; their target; each skill against their class; and every class they are or were on (from the class lists, so subjects with no marking yet appear too). Take pupil_id from pupil_list or results_get. A pupil with no marking the caller may see returns found: false. Read-only.
| Name | Required | Description | Default |
|---|---|---|---|
| scope | No | "department" (default) reads the pupil across everything the caller may see; "mine" only the caller's own marking. | department |
| subject | No | Which subject to read them in. Omit for the subject with the most marking. | |
| pupil_id | Yes | The pupil's id, from pupil_list or results_get. | |
| academic_year_id | No | The year their target is read for. Omit for the current year. |
Output Schema
| Name | Required | Description |
|---|---|---|
| found | Yes | False when there is no marked work for this pupil that the caller may see. |
| pupil | Yes | |
| scope | Yes | |
| scope_note | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint/idempotent/openWorld false, and the description sensibly restates 'Read-only.' It adds real behavioral value: 'A pupil with no marking the caller may see returns found: false,' and notes class data comes from class lists so unmarked subjects still appear. This edge-case and data-provenance disclosure goes beyond the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the resource and its content; dense but every clause describes a distinct part of the return. The semicolon-chained enumeration is efficient if slightly heavy, with no filler sentences.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema and full annotations, the description is complete enough: it covers scope of returned data, the found:false case, and where to source pupil_id. It slightly over-explains return fields already in the output schema, but nothing critical is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so parameters (scope, subject default-to-most-marking, academic_year_id, pupil_id) are fully documented in the schema. The description mostly echoes this and only adds the provenance of pupil_id, leaving baseline 3 appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific resource (one pupil in one subject) and enumerates the returned artifacts: assessments across years with dates/grade/percentage, change since previous, target, skills vs class, and class enrollment history. An agent can clearly distinguish this from pupil_list (which enumerates pupils) and results_get.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly routes the agent for the required parameter: 'Take pupil_id from pupil_list or results_get.' That gives a clear entry path, but there is no explicit when-to-use-it-vs-siblings or exclusion statement (beyond the found:false edge case).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
pupil_listList PupilsARead-onlyIdempotentInspect
Pupils to act on, as the dashboard's pupil tabs list them: "watch" (dropped half a grade or more, a grade or more below target, or well behind their class on a skill), "thriving", "below" (below target), "drop" (biggest drop, steepest first) or "all". Each pupil comes with their latest grade, the change since their previous assessment, their target and the reason they are listed. Narrow with the same filters as results_get. Paged: pass next_offset as offset for the next page. Each pupil's link comes from pupil_get. Read-only.
| Name | Required | Description | Default |
|---|---|---|---|
| list | No | Which pupils, matching the dashboard's pupil tabs. "watch" (default): dropped half a grade or more, a grade or more below target, or well behind their class on a skill. "thriving": climbed, at or above target, or strongest in their year on a skill. "below": a grade or more below target. "drop": everyone who dropped, steepest first. "all": every pupil, weakest first. | watch |
| limit | No | Most pupils to return in one page. | |
| scope | No | "department" (default) is the widest view the caller may see: the whole school for a school admin, their department for a head of department. Anyone else is given their own marking, and the answer says so. "mine" is always the caller's own marking. | department |
| offset | No | Pupils to skip, for the next page: pass next_offset from the previous answer. | |
| subject | No | Narrow to one subject. | |
| class_id | No | Narrow to one class. Ids come from results_get. | |
| year_group | No | Narrow to one year group, exactly as results_get returns it in cohorts[].year_group: usually its number, "11" for Year 11. | |
| academic_year_id | No | An academic year id (from results_get), or "all" for every year including marking filed under no assessment. Omit for the current year. | |
| assessment_point_id | No | Narrow to one assessment point (a school's data drop, e.g. 'Y11 Mock 1'). Ids come from results_get. |
Output Schema
| Name | Required | Description |
|---|---|---|
| list | Yes | |
| scope | Yes | |
| total | Yes | Pupils on this list, across every page. |
| offset | Yes | |
| pupils | Yes | |
| heading | Yes | |
| scope_note | Yes | |
| next_offset | Yes | Pass as offset for the next page; null on the last page. |
| empty_reason | Yes | Why the list is empty, when it is. |
| dashboard_url | Yes | |
| filters_applied | Yes | |
| filters_dropped | Yes | Filters that matched nothing the caller can see and were NOT applied. |
| too_many_to_list | Yes | Cohorts with too many pupils to list (over 60, as on the dashboard). Ask again per class with class_id to see them. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well past the annotations (which only cover readOnly/idempotent/closed-world) by disclosing pagination mechanics, result ordering per tab ("steepest first", "weakest first"), the fields returned per pupil (latest grade, change, target, listing reason), and the role-dependent scope resolution including that the answer self-reports when the view was downgraded.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with scope and the tab taxonomy, then routing, then paging, then the read-only note. Efficient, though the per-tab definitions largely restate the enum descriptions in the schema and drift the sentence long.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists so return values needn't be explained, and 0 required params with 9 total filters means defaults carry the call. The definition covers the tab choice, scope semantics and paging loop; only the interaction between multiple simultaneous filters is left implicit.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 100% schema coverage the baseline is 3; the description earns more by tying `offset` to the paging loop (pass next_offset) and by framing subject/class/year/assessment_point filters as sharing results_get's semantics, which the schema alone does not convey.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific resource (pupils) and the exact taxonomy of views it returns (watch/thriving/below/drop/all), each defined by a concrete criterion. It also disambiguates from the two closest siblings: filters come from results_get and per-pupil detail comes from pupil_get.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Clear routing: use the same filters as results_get to narrow, and pupil_get for the individual pupil link. It also tells the agent to page via next_offset. It stops short of an explicit statement of when NOT to use it (e.g. use results_get when you need raw assessment results rather than a pupil roster), leaving that to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
question_updateUpdate Question by IDBIdempotentInspect
Update an existing GCSE question by its ID
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | The unique identifier for the question to update | |
| topic | No | The topic or subject matter for the question | |
| points | No | Number of marks the question is worth | |
| subject | No | Subject area for the question | |
| question_text | No | The exam question | |
| difficulty_level | No | Difficulty level of the question |
Output Schema
| Name | Required | Description |
|---|---|---|
| topic | Yes | |
| points | Yes | |
| subject | Yes | |
| updated | Yes | Names of the fields written by this call. |
| question_id | Yes | |
| difficulty_level | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare idempotentHint=true, destructiveHint=false, and openWorldHint=false, so the safety profile is covered. The description adds the precondition that the question must already exist ('existing'), but says nothing about partial-update semantics — whether omitted fields are left unchanged or cleared — which is the key behavioral question for an update tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single front-loaded sentence with zero filler; nothing is redundant. It is arguably too terse for a mutation tool, but that shortfall is better attributed to completeness than to verbosity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a mutation tool with five optional fields, the description omits partial-update semantics, required-role/permission context, and behavior when the ID does not exist. The output schema covers return values and annotations cover safety, but the core update contract is undocumented.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% with enums documented for subject and difficulty_level, so the schema fully carries parameter meaning. The description contributes no additional detail such as whether at least one updatable field is required alongside id.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Update an existing GCSE question') plus the addressing key ('by its ID'), which is enough to distinguish it from sibling readers like ingestion_get or submission_mark. It does not explicitly contrast with markScheme_update, but the resource noun differs, so confusion risk is low.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance on when to use this rather than markScheme_update or paper_confirm, and no guidance on the update workflow (e.g., whether to fetch first, whether to send all fields or only changed ones). The agent must infer everything from the schema.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
results_getGet ResultsARead-onlyIdempotentInspect
How a school, department, year group or class is doing: average grade and percentage per cohort (one subject, one year group), the change since the previous assessment, strongest and weakest skills, and every class. With no filters it is also the overview — the academic years, the assessment points (data drops) and the cohorts, with the ids the filters and the pupil tools take. Over 12 cohorts (a whole school) it returns each cohort's headline only (detail: summary); narrow by subject or year_group for classes and skills. Grades are written as the dashboard writes them (a group's average to one decimal, e.g. 4.6). Read-only. Quote these figures rather than recomputing them, and share dashboard_url so the teacher can open the same view.
| Name | Required | Description | Default |
|---|---|---|---|
| scope | No | "department" (default) is the widest view the caller may see: the whole school for a school admin, their department for a head of department. Anyone else is given their own marking, and the answer says so. "mine" is always the caller's own marking. | department |
| subject | No | Narrow to one subject. | |
| class_id | No | Narrow to one class. Ids come from results_get. | |
| year_group | No | Narrow to one year group, exactly as results_get returns it in cohorts[].year_group: usually its number, "11" for Year 11. | |
| academic_year_id | No | An academic year id (from results_get), or "all" for every year including marking filed under no assessment. Omit for the current year. | |
| assessment_point_id | No | Narrow to one assessment point (a school's data drop, e.g. 'Y11 Mock 1'). Ids come from results_get. |
Output Schema
| Name | Required | Description |
|---|---|---|
| year | Yes | |
| scope | Yes | |
| years | Yes | |
| detail | Yes | "summary" when there were more than 12 cohorts: each cohort's classes and skills are left out (empty). Narrow by subject or year_group for them. |
| cohorts | Yes | |
| heading | Yes | What this is, e.g. 'English' or 'Your marking'. |
| scope_note | Yes | Why the caller got less than they asked for, if they did. |
| dashboard_url | Yes | |
| filters_applied | Yes | |
| filters_dropped | Yes | Filters that matched nothing the caller can see and were NOT applied. |
| unfiled_scripts | Yes | Marked scripts filed under no assessment point, outside every year. Ask again with academic_year_id 'all' to include them. |
| assessment_points | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare read-only, and the description reinforces it while adding non-obvious behavior the schema cannot: the 12-cohort truncation rule that returns headline only, the exact grade formatting convention ('a group's average to one decimal'), and the instruction to quote figures and share dashboard_url rather than recompute. That is real behavioral context beyond the structured fields, with no contradiction of readOnlyHint.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with purpose, then behavior, then a usage instruction — a sensible order. It is dense (two long sentences packing multiple clauses) but nearly every clause earns its place; minor trimming of the grade-formatting aside would tighten it.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present the description needn't describe return shapes, and it still covers the edge case that matters (large-cohort truncation), the id provenance needed to chain calls, and the read-only safety profile. Nothing an agent needs to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3; the description goes further by establishing where ids come from (self-referentially from results_get/cohorts) and tying the absence of filters to the overview mode, which clarifies the default behavior of scope/academic_year_id. It adds orientation beyond the schema but not per-parameter syntax detail.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a specific verb-plus-resource framing ('How a school, department, year group or class is doing: average grade and percentage per cohort') and enumerates the exact outputs (average grade, percentage, change since previous assessment, strongest/weakest skills, every class). The dual mode — filtered cohort view vs. no-filter overview returning academic years, assessment points and cohort ids — makes it unmistakable against siblings like markResult_get or pupil_list.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly says what happens with no filters (it becomes the overview supplying the ids the filters and pupil tools take) and when to narrow ('over 12 cohorts... narrow by subject or year_group for classes and skills'). It does not name a sibling alternative for the detail-vs-summary decision beyond the 'detail: summary' hint, so it stops just short of a full when/when-not/alternative statement.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
submission_getGet Submission Grading ResultARead-onlyIdempotentInspect
Read the grading state and per-question marks for a submission (created via submission_mark). Returns each question's marking_status, awarded/max marks, level, and feedback, plus an overall status ('grading' until every question is marked). Poll after submission_mark.
| Name | Required | Description | Default |
|---|---|---|---|
| submission_id | Yes | ID of the submission to read grading results for. |
Output Schema
| Name | Required | Description |
|---|---|---|
| status | Yes | Overall grading status. |
| questions | Yes | |
| total_max | Yes | Total marks available, null until grading is complete. |
| student_name | Yes | Detected student name, or null if none was read. |
| exam_paper_id | Yes | |
| grading_error | Yes | Failure detail when status is failed. |
| submission_id | Yes | |
| total_awarded | Yes | Total marks awarded, null until grading is complete. |
| questions_marked | Yes | Progress as "marked/total", e.g. "3/6". |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and openWorldHint=false, so the safety profile is covered. The description adds useful behavior beyond annotations by explaining the overall status remains 'grading' until every question is marked and that per-question marking_status, marks, level, and feedback are returned.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and front-loaded with the core read operation. The second sentence adds the polling instruction without unnecessary detail, and every element supports either selection or correct invocation.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given a single required parameter, full schema coverage, rich annotations, and an output schema, the description is complete enough. It covers the operation, output contents, and polling context without needing to duplicate the output schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% for the single submission_id parameter, so the schema already documents it fully. The description only implies the submission relationship via 'created via submission_mark' and does not add parameter-specific semantics beyond that baseline.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb and resource: it reads grading state and per-question marks for a submission. It also distinguishes the tool from submission_mark by noting that submissions are created via that sibling and that this tool should be polled afterward.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly says to poll after submission_mark and identifies the parent operation that creates the submission. It does not name an alternative such as results_get or markResult_get, so it lacks explicit when-not guidance but gives clear usage context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
submission_markMark a Student Submission from TextAInspect
Mark a student's typed answers against an existing exam paper. Provide the exam_paper_id and per-question answers keyed by question_number. DeepMark creates a submission and grades it through its canonical marker (per mark point / level descriptor) — results stream into the teacher's editor live. Grading is asynchronous: this returns a submission_id; poll submission_get for the per-question grades.
| Name | Required | Description | Default |
|---|---|---|---|
| answers | Yes | One entry per answered question, keyed to its question by number. DeepMark grades each answer against that question's mark scheme via the canonical marker. | |
| student_name | No | The student's name, surfaced in results. Optional. | |
| exam_paper_id | Yes | The exam paper to mark these answers against. |
Output Schema
| Name | Required | Description |
|---|---|---|
| poll_with | Yes | The tool to poll this submission with (submission_get). |
| exam_paper_id | Yes | |
| submission_id | Yes | |
| answers_submitted | Yes | How many answers matched a question and were queued for grading. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations: it discloses that this is a mutating, asynchronous operation that creates a submission record, returns only a submission_id, and requires polling submission_get for grades. It also explains that results stream live into the teacher's editor, which the non-idempotent/create semantics alone would not convey.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, no filler, with the core action first, then required inputs, then the async-return caveat front-loaded before an agent would try to read grades from the response.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a create-and-grade tool with an output schema, the description covers what an agent needs to call it correctly: inputs, mutation semantics, and the fact that the response is a submission_id requiring a follow-up poll. Nothing material is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the schema already documents exam_paper_id, answers, question_number and answer_text in detail. The description only restates that answers are keyed by question_number, adding no format or constraint detail beyond the schema — baseline 3.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Mark a student's typed answers against an existing exam paper') and names the canonical grading path, which clearly separates it from submission_get, markResult_get and results_get. An agent can tell exactly what this tool produces without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly states the prerequisite (an existing exam paper via exam_paper_id) and names the follow-up tool ('poll submission_get'). It does not state when *not* to use it (e.g. use a different tool for pre-existing submissions or non-text input), so it stops short of full routing guidance.
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.
13 tool updates
- Changed
ingestion_get1 field changed- removed
Output schema / additionalPropertiesRemoved value: -false
- Changed
markResult_get3 fields changed- removed
Output schema / additionalPropertiesRemoved value: -false - removed
Output schema / properties / mark_points / items / additionalPropertiesRemoved value: -false - removed
Output schema / properties / mark_scheme / additionalPropertiesRemoved value: -false
- Changed
markScheme_update1 field changed- removed
Output schema / additionalPropertiesRemoved value: -false
- Changed
paper_confirm1 field changed- removed
Output schema / additionalPropertiesRemoved value: -false
- Changed
paper_create1 field changed- removed
Output schema / additionalPropertiesRemoved value: -false
- Changed
paper_get6 fields changed- removed
Output schema / additionalPropertiesRemoved value: -false - changed
Output schema / properties / created_by / anyOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "email": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ] - }, - "id": { - "type": "string" - }, - "name": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ] - } - }, - "required": [ - "id", - "name", - "email" - ], - "type": "object" - }, - { - "type": "null" - } -]New value: +[ + { + "properties": { + "email": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "id": { + "type": "string" + }, + "name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "id", + "name", + "email" + ], + "type": "object" + }, + { + "type": "null" + } +] - removed
Output schema / properties / sections / items / additionalPropertiesRemoved value: -false - removed
Output schema / properties / sections / items / properties / questions / items / additionalPropertiesRemoved value: -false - removed
Output schema / properties / sections / items / properties / questions / items / properties / mark_schemes / items / additionalPropertiesRemoved value: -false - removed
Output schema / properties / sections / items / properties / questions / items / properties / mark_schemes / items / properties / mark_points / items / additionalPropertiesRemoved value: -false
- Changed
paper_list3 fields changed- removed
Output schema / additionalPropertiesRemoved value: -false - removed
Output schema / properties / papers / items / additionalPropertiesRemoved value: -false - changed
Output schema / properties / papers / items / properties / created_by / anyOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "email": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ] - }, - "id": { - "type": "string" - }, - "name": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ] - } - }, - "required": [ - "id", - "name", - "email" - ], - "type": "object" - }, - { - "type": "null" - } -]New value: +[ + { + "properties": { + "email": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "id": { + "type": "string" + }, + "name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "id", + "name", + "email" + ], + "type": "object" + }, + { + "type": "null" + } +]
- Changed
pupil_get2 fields changed- removed
Output schema / additionalPropertiesRemoved value: -false - changed
Output schema / properties / pupil / anyOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "assessments": { - "items": { - "additionalProperties": false, - "properties": { - "grade": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ] - }, - "grade_exact": { - "anyOf": [ - { - "type": "number" - }, - { - "type": "null" - } - ], - "description": "The grade with its fraction, cut (not rounded) to one decimal: 3.6 is a 3+. The change between assessments is read from these, so two papers can share a grade and a percentage and still differ by a few tenths when their boundaries differ." - }, - "label": { - "description": "The assessment as the dashboard names it.", - "type": "string" - }, - "paper_title": { - "type": "string" - }, - "percent": { - "anyOf": [ - { - "type": "number" - }, - { - "type": "null" - } - ] - } - }, - "required": [ - "label", - "paper_title", - "percent", - "grade", - "grade_exact" - ], - "type": "object" - }, - "type": "array" - }, - "change": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ] - }, - "class_code": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ] - }, - "dashboard_url": { - "type": "string" - }, - "grade_change": { - "anyOf": [ - { - "type": "number" - }, - { - "type": "null" - } - ] - }, - "latest_grade": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ] - }, - "latest_percent": { - "type": "number" - }, - "name": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ] - }, - "other_subjects": { - "items": { - "type": "string" - }, - "type": "array" - }, - "percent_change": { - "anyOf": [ - { - "type": "number" - }, - { - "type": "null" - } - ] - }, - "pupil_id": { - "type": "string" - }, - "skills": { - "items": { - "additionalProperties": false, - "properties": { - "code": { - "type": "string" - }, - "group_percent": { - "anyOf": [ - { - "type": "number" - }, - { - "type": "null" - } - ], - "description": "Their class (or teacher's group) on the same skill, for comparison." - }, - "pupil_percent": { - "type": "number" - } - }, - "required": [ - "code", - "pupil_percent", - "group_percent" - ], - "type": "object" - }, - "type": "array" - }, - "subject": { - "type": "string" - }, - "subject_label": { - "type": "string" - }, - "target": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ] - }, - "teacher": { - "type": "string" - }, - "year_group": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ] - } - }, - "required": [ - "pupil_id", - "name", - "subject", - "subject_label", - "other_subjects", - "class_code", - "year_group", - "teacher", - "latest_grade", - "latest_percent", - "change", - "grade_change", - "percent_change", - "target", - "assessments", - "skills", - "dashboard_url" - ], - "type": "object" - }, - { - "type": "null" - } -]New value: +[ + { + "properties": { + "assessments": { + "description": "Every assessment in this subject that they or their group sat, across all years, in the order sat. percent null = they did not sit it.", + "items": { + "properties": { + "academic_year": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The school year it counts towards, e.g. \"2026/27\"; null for a paper filed under no assessment point." + }, + "date": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When it was sat (YYYY-MM-DD), where the paper is dated." + }, + "grade": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "grade_exact": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "description": "The grade with its fraction, cut (not rounded) to one decimal: 3.6 is a 3+. The change between assessments is read from these, so two papers can share a grade and a percentage and still differ by a few tenths when their boundaries differ." + }, + "label": { + "description": "The assessment as the dashboard names it.", + "type": "string" + }, + "paper_title": { + "type": "string" + }, + "percent": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "label", + "paper_title", + "percent", + "grade", + "grade_exact", + "date", + "academic_year" + ], + "type": "object" + }, + "type": "array" + }, + "change": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "class_code": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "classes": { + "description": "Every class they are or were on, newest year first, from the class lists rather than the marking — so a subject with no marking yet still appears. Only classes the caller may see: their department's for a head of department, every class for a school admin.", + "items": { + "properties": { + "academic_year": { + "type": "string" + }, + "class_code": { + "type": "string" + }, + "class_id": { + "type": "string" + }, + "current": { + "description": "On this class today.", + "type": "boolean" + }, + "subject": { + "type": "string" + }, + "subject_label": { + "type": "string" + }, + "teachers": { + "items": { + "type": "string" + }, + "type": "array" + }, + "year_group": { + "type": "string" + } + }, + "required": [ + "class_id", + "class_code", + "subject", + "subject_label", + "year_group", + "academic_year", + "teachers", + "current" + ], + "type": "object" + }, + "type": "array" + }, + "dashboard_url": { + "type": "string" + }, + "grade_change": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ] + }, + "latest_grade": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "latest_percent": { + "type": "number" + }, + "name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "other_subjects": { + "items": { + "type": "string" + }, + "type": "array" + }, + "percent_change": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ] + }, + "pupil_id": { + "type": "string" + }, + "skills": { + "items": { + "properties": { + "code": { + "type": "string" + }, + "group_percent": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "description": "Their class (or teacher's group) on the same skill, for comparison." + }, + "pupil_percent": { + "type": "number" + } + }, + "required": [ + "code", + "pupil_percent", + "group_percent" + ], + "type": "object" + }, + "type": "array" + }, + "subject": { + "type": "string" + }, + "subject_label": { + "type": "string" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "teacher": { + "type": "string" + }, + "year_group": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "pupil_id", + "name", + "subject", + "subject_label", + "other_subjects", + "class_code", + "year_group", + "teacher", + "latest_grade", + "latest_percent", + "change", + "grade_change", + "percent_change", + "target", + "classes", + "assessments", + "skills", + "dashboard_url" + ], + "type": "object" + }, + { + "type": "null" + } +]
- Changed
pupil_list4 fields changed- removed
Output schema / additionalPropertiesRemoved value: -false - removed
Output schema / properties / filters_applied / items / additionalPropertiesRemoved value: -false - removed
Output schema / properties / filters_dropped / items / additionalPropertiesRemoved value: -false - removed
Output schema / properties / pupils / items / additionalPropertiesRemoved value: -false
- Changed
question_update1 field changed- removed
Output schema / additionalPropertiesRemoved value: -false
- Changed
results_get10 fields changed- removed
Output schema / additionalPropertiesRemoved value: -false - removed
Output schema / properties / assessment_points / items / additionalPropertiesRemoved value: -false - removed
Output schema / properties / cohorts / items / additionalPropertiesRemoved value: -false - removed
Output schema / properties / cohorts / items / properties / change / additionalPropertiesRemoved value: -false - removed
Output schema / properties / cohorts / items / properties / classes / items / additionalPropertiesRemoved value: -false - removed
Output schema / properties / cohorts / items / properties / skills / items / additionalPropertiesRemoved value: -false - removed
Output schema / properties / filters_applied / items / additionalPropertiesRemoved value: -false - removed
Output schema / properties / filters_dropped / items / additionalPropertiesRemoved value: -false - changed
Output schema / properties / year / anyOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "id": { - "type": "string" - }, - "label": { - "type": "string" - } - }, - "required": [ - "id", - "label" - ], - "type": "object" - }, - { - "type": "null" - } -]New value: +[ + { + "properties": { + "id": { + "type": "string" + }, + "label": { + "type": "string" + } + }, + "required": [ + "id", + "label" + ], + "type": "object" + }, + { + "type": "null" + } +] - removed
Output schema / properties / years / items / additionalPropertiesRemoved value: -false
- Changed
submission_get2 fields changed- removed
Output schema / additionalPropertiesRemoved value: -false - removed
Output schema / properties / questions / items / additionalPropertiesRemoved value: -false
- Changed
submission_mark1 field changed- removed
Output schema / additionalPropertiesRemoved value: -false
1 tool update
- Changed
pupil_get1 field changed- changed
Output schema / properties / pupil / anyOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "assessments": { - "items": { - "additionalProperties": false, - "properties": { - "grade": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ] - }, - "label": { - "description": "The assessment as the dashboard names it.", - "type": "string" - }, - "paper_title": { - "type": "string" - }, - "percent": { - "anyOf": [ - { - "type": "number" - }, - { - "type": "null" - } - ] - } - }, - "required": [ - "label", - "paper_title", - "percent", - "grade" - ], - "type": "object" - }, - "type": "array" - }, - "change": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ] - }, - "class_code": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ] - }, - "dashboard_url": { - "type": "string" - }, - "grade_change": { - "anyOf": [ - { - "type": "number" - }, - { - "type": "null" - } - ] - }, - "latest_grade": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ] - }, - "latest_percent": { - "type": "number" - }, - "name": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ] - }, - "other_subjects": { - "items": { - "type": "string" - }, - "type": "array" - }, - "percent_change": { - "anyOf": [ - { - "type": "number" - }, - { - "type": "null" - } - ] - }, - "pupil_id": { - "type": "string" - }, - "skills": { - "items": { - "additionalProperties": false, - "properties": { - "code": { - "type": "string" - }, - "group_percent": { - "anyOf": [ - { - "type": "number" - }, - { - "type": "null" - } - ], - "description": "Their class (or teacher's group) on the same skill, for comparison." - }, - "pupil_percent": { - "type": "number" - } - }, - "required": [ - "code", - "pupil_percent", - "group_percent" - ], - "type": "object" - }, - "type": "array" - }, - "subject": { - "type": "string" - }, - "subject_label": { - "type": "string" - }, - "target": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ] - }, - "teacher": { - "type": "string" - }, - "year_group": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ] - } - }, - "required": [ - "pupil_id", - "name", - "subject", - "subject_label", - "other_subjects", - "class_code", - "year_group", - "teacher", - "latest_grade", - "latest_percent", - "change", - "grade_change", - "percent_change", - "target", - "assessments", - "skills", - "dashboard_url" - ], - "type": "object" - }, - { - "type": "null" - } -]New value: +[ + { + "additionalProperties": false, + "properties": { + "assessments": { + "items": { + "additionalProperties": false, + "properties": { + "grade": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "grade_exact": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "description": "The grade with its fraction, cut (not rounded) to one decimal: 3.6 is a 3+. The change between assessments is read from these, so two papers can share a grade and a percentage and still differ by a few tenths when their boundaries differ." + }, + "label": { + "description": "The assessment as the dashboard names it.", + "type": "string" + }, + "paper_title": { + "type": "string" + }, + "percent": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "label", + "paper_title", + "percent", + "grade", + "grade_exact" + ], + "type": "object" + }, + "type": "array" + }, + "change": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "class_code": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "dashboard_url": { + "type": "string" + }, + "grade_change": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ] + }, + "latest_grade": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "latest_percent": { + "type": "number" + }, + "name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "other_subjects": { + "items": { + "type": "string" + }, + "type": "array" + }, + "percent_change": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ] + }, + "pupil_id": { + "type": "string" + }, + "skills": { + "items": { + "additionalProperties": false, + "properties": { + "code": { + "type": "string" + }, + "group_percent": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "description": "Their class (or teacher's group) on the same skill, for comparison." + }, + "pupil_percent": { + "type": "number" + } + }, + "required": [ + "code", + "pupil_percent", + "group_percent" + ], + "type": "object" + }, + "type": "array" + }, + "subject": { + "type": "string" + }, + "subject_label": { + "type": "string" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "teacher": { + "type": "string" + }, + "year_group": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "pupil_id", + "name", + "subject", + "subject_label", + "other_subjects", + "class_code", + "year_group", + "teacher", + "latest_grade", + "latest_percent", + "change", + "grade_change", + "percent_change", + "target", + "assessments", + "skills", + "dashboard_url" + ], + "type": "object" + }, + { + "type": "null" + } +]
3 tool updates
- Added
pupil_get - Added
pupil_list - Added
results_get
2 tool updates
- Changed
paper_confirm1 field changed- removed
Input schema / properties / metadata / properties / year_groupRemoved value: -{ - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "Override the detected class / year group." -}
- Changed
paper_create1 field changed- removed
Input schema / properties / hints / properties / year_groupRemoved value: -{ - "description": "Teacher's class / year group — free text, e.g. 'Year 11'.", - "type": "string" -}
10 tool updates
- Changed
ingestion_get2 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
- Changed
markResult_get2 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
- Changed
markScheme_update2 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
- Changed
paper_confirm2 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
- Changed
paper_create2 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
- Changed
paper_get2 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
- Changed
paper_list2 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
- Changed
question_update2 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
- Changed
submission_get2 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
- Changed
submission_mark2 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
3 tool updates
- Changed
markResult_get2 fields changed- removed
Output schema / properties / mark_scheme / properties / points_totalRemoved value: -{ - "type": "number" -} - changed
Output schema / properties / mark_scheme / requiredPrevious value: -[ - "description", - "points_total", - "tags", - "guidance" -]New value: +[ + "description", + "tags", + "guidance" +]
- Changed
markScheme_update4 fields changed- changed
Input schema / properties / points_total / descriptionPrevious value: -"Total number of points for the mark scheme"New value: +"The question's total marks. Stored on the question — a mark scheme is always out of its question's total." - added
Output schema / properties / points_total / anyOfAdded value: +[ + { + "type": "number" + }, + { + "type": "null" + } +] - added
Output schema / properties / points_total / descriptionAdded value: +"The question's total marks after the update." - removed
Output schema / properties / points_total / typeRemoved value: -"number"
- Changed
paper_get2 fields changed- removed
Output schema / properties / sections / items / properties / questions / items / properties / mark_schemes / items / properties / points_totalRemoved value: -{ - "type": "number" -} - changed
Output schema / properties / sections / items / properties / questions / items / properties / mark_schemes / items / requiredPrevious value: -[ - "id", - "description", - "marking_method", - "points_total", - "mark_points", - "content" -]New value: +[ + "id", + "description", + "marking_method", + "mark_points", + "content" +]
1 tool update
- Changed
ingestion_get2 fields changed- changed
Output schema / properties / awaiting / anyOfPrevious value: -[ - { - "enum": [ - "triage", - "confirmation" - ], - "type": "string" - }, - { - "type": "null" - } -]New value: +[ + { + "enum": [ + "start", + "triage", + "confirmation" + ], + "type": "string" + }, + { + "type": "null" + } +] - changed
Output schema / properties / awaiting / descriptionPrevious value: -"The gate the job is parked at, or null if none."New value: +"The gate the job is parked at, or null if none. `start` means it has not been handed to a queue at all and a person must act before it is — polling will never resolve it."
1 tool update
- Changed
paper_confirm1 field changed- added
Input schema / properties / metadata / properties / assessment_dateAdded value: +{ + "anyOf": [ + { + "pattern": "^\\d{4}-\\d{2}-\\d{2}$", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When this cohort SAT the paper, as YYYY-MM-DD. Never detected — it is a fact about a school, not about the paper — so it is only ever set here. Omit when nobody has said." +}
2 tool updates
- Changed
paper_get5 fields changed- removed
Output schema / properties / created_by / additionalPropertiesRemoved value: -false - added
Output schema / properties / created_by / anyOfAdded value: +[ + { + "additionalProperties": false, + "properties": { + "email": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "id": { + "type": "string" + }, + "name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "id", + "name", + "email" + ], + "type": "object" + }, + { + "type": "null" + } +] - removed
Output schema / properties / created_by / propertiesRemoved value: -{ - "email": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ] - }, - "id": { - "type": "string" - }, - "name": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ] - } -} - removed
Output schema / properties / created_by / requiredRemoved value: -[ - "id", - "name", - "email" -] - removed
Output schema / properties / created_by / typeRemoved value: -"object"
- Changed
paper_list5 fields changed- removed
Output schema / properties / papers / items / properties / created_by / additionalPropertiesRemoved value: -false - added
Output schema / properties / papers / items / properties / created_by / anyOfAdded value: +[ + { + "additionalProperties": false, + "properties": { + "email": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "id": { + "type": "string" + }, + "name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "id", + "name", + "email" + ], + "type": "object" + }, + { + "type": "null" + } +] - removed
Output schema / properties / papers / items / properties / created_by / propertiesRemoved value: -{ - "email": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ] - }, - "id": { - "type": "string" - }, - "name": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ] - } -} - removed
Output schema / properties / papers / items / properties / created_by / requiredRemoved value: -[ - "id", - "name", - "email" -] - removed
Output schema / properties / papers / items / properties / created_by / typeRemoved value: -"object"
10 tool updates
- First observed
ingestion_get - First observed
markResult_get - First observed
markScheme_update - First observed
paper_confirm - First observed
paper_create - First observed
paper_get - First observed
paper_list - First observed
question_update - First observed
submission_get - First observed
submission_mark
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceRemote MCP server that lets AI assistants read tracked competitive intelligence — competitor news, reviews, website changes, social posts and ads — and act on it by managing projects, competitors, battle cards, reports and canvases. Every answer carries a source and a date, and write actions only publish when explicitly shared.MIT
- AlicenseCqualityBmaintenanceCompetitor Monitor AI - MCP server providing AI-powered tools and automation by MEOK AI Labs115 npm58 PyPIMIT
- AlicenseAqualityCmaintenanceEnables brand visibility monitoring across major AI platforms like ChatGPT, Claude, Gemini, and Perplexity. It allows users to track visibility scores, analyze competitor data, and receive actionable insights to improve AI-generated brand recommendations.1618 npm1MIT

industrylens-mcpofficial
AlicenseNot gradedqualityBmaintenanceBrowse IndustryLens's published competitive-intelligence reports and head-to-head competitor comparisons from any AI agent — real, source-backed data.MIT
Glama MCP Gateway
Add one secure layer between your agents and this server.