Upload exercise figure
upload_exercise_figure
Section titled “upload_exercise_figure”Use this to attach one reviewed image, MCP file, HTTPS image, base64 image, or rendered figure to an exercise by providing exerciseId, figureType, source, and width.
Contract metadata
Section titled “Contract metadata”{ "annotations": { "readOnlyHint": false, "destructiveHint": false, "idempotentHint": false, "openWorldHint": true }, "fileParams": [ "file_id_1" ], "requiredPermission": "write", "security": { "type": "oauth2", "scopes": [ "chalksurf:mcp" ] }}Input schema
Section titled “Input schema”The server advertises this JSON Schema to MCP clients. Runtime authorization and business-rule checks still apply.
{ "$schema": "https://json-schema.org/draft/2020-12/schema", "additionalProperties": {}, "properties": { "allowNeedsRevision": { "type": "boolean" }, "exerciseId": { "format": "uuid", "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$", "type": "string" }, "figureType": { "enum": [ "text", "solution" ], "type": "string" }, "file_id_1": { "additionalProperties": false, "description": "A ChatGPT file ID.", "properties": { "download_url": { "format": "uri", "type": "string" }, "file_id": { "minLength": 1, "type": "string" }, "file_name": { "minLength": 1, "type": "string" }, "mime_type": { "minLength": 1, "type": "string" } }, "required": [ "download_url", "file_id" ], "type": "object" }, "organizationId": { "description": "The ChalkSurf organization ID to use for this request.", "format": "uuid", "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$", "type": "string" }, "originalFileName": { "maxLength": 255, "minLength": 1, "type": "string" }, "source": { "additionalProperties": {}, "description": "A figure source object. Use file_id_1 for ChatGPT file uploads; for rendered_figure, include input using the figure_render_draft shape.", "properties": { "data": { "maxLength": 14680064, "minLength": 1, "type": "string" }, "input": { "additionalProperties": {}, "description": "Call figure_get_capabilities first. Unknown properties are ignored with warnings; recognized invalid combinations fail with actionable paths.", "properties": { "assertions": { "items": { "additionalProperties": {}, "properties": { "angleA": { "items": { "description": "A stable figure object identifier such as A, AB, c1, or angle_mark_1.", "pattern": "^[A-Za-z][A-Za-z0-9_-]{0,31}$", "type": "string" }, "maxItems": 3, "minItems": 3, "type": "array" }, "angleB": { "items": { "description": "A stable figure object identifier such as A, AB, c1, or angle_mark_1.", "pattern": "^[A-Za-z][A-Za-z0-9_-]{0,31}$", "type": "string" }, "maxItems": 3, "minItems": 3, "type": "array" }, "bisector": { "description": "A stable figure object identifier such as A, AB, c1, or angle_mark_1.", "pattern": "^[A-Za-z][A-Za-z0-9_-]{0,31}$", "type": "string" }, "circle": { "description": "A stable figure object identifier such as A, AB, c1, or angle_mark_1.", "pattern": "^[A-Za-z][A-Za-z0-9_-]{0,31}$", "type": "string" }, "degrees": { "maximum": 360, "minimum": 0, "type": "number" }, "from": { "description": "A stable figure object identifier such as A, AB, c1, or angle_mark_1.", "pattern": "^[A-Za-z][A-Za-z0-9_-]{0,31}$", "type": "string" }, "id": { "description": "A stable figure object identifier such as A, AB, c1, or angle_mark_1.", "pattern": "^[A-Za-z][A-Za-z0-9_-]{0,31}$", "type": "string" }, "line": { "description": "A stable figure object identifier such as A, AB, c1, or angle_mark_1.", "pattern": "^[A-Za-z][A-Za-z0-9_-]{0,31}$", "type": "string" }, "lineObject": { "description": "A stable figure object identifier such as A, AB, c1, or angle_mark_1.", "pattern": "^[A-Za-z][A-Za-z0-9_-]{0,31}$", "type": "string" }, "objectA": { "description": "A stable figure object identifier such as A, AB, c1, or angle_mark_1.", "pattern": "^[A-Za-z][A-Za-z0-9_-]{0,31}$", "type": "string" }, "objectB": { "description": "A stable figure object identifier such as A, AB, c1, or angle_mark_1.", "pattern": "^[A-Za-z][A-Za-z0-9_-]{0,31}$", "type": "string" }, "objects": { "items": { "description": "A stable figure object identifier such as A, AB, c1, or angle_mark_1.", "pattern": "^[A-Za-z][A-Za-z0-9_-]{0,31}$", "type": "string" }, "maxItems": 8, "minItems": 3, "type": "array" }, "point": { "description": "A stable figure object identifier such as A, AB, c1, or angle_mark_1.", "pattern": "^[A-Za-z][A-Za-z0-9_-]{0,31}$", "type": "string" }, "pointA": { "description": "A stable figure object identifier such as A, AB, c1, or angle_mark_1.", "pattern": "^[A-Za-z][A-Za-z0-9_-]{0,31}$", "type": "string" }, "pointB": { "description": "A stable figure object identifier such as A, AB, c1, or angle_mark_1.", "pattern": "^[A-Za-z][A-Za-z0-9_-]{0,31}$", "type": "string" }, "points": { "items": { "description": "A stable figure object identifier such as A, AB, c1, or angle_mark_1.", "pattern": "^[A-Za-z][A-Za-z0-9_-]{0,31}$", "type": "string" }, "maxItems": 8, "minItems": 3, "type": "array" }, "segmentA": { "description": "A stable figure object identifier such as A, AB, c1, or angle_mark_1.", "pattern": "^[A-Za-z][A-Za-z0-9_-]{0,31}$", "type": "string" }, "segmentB": { "description": "A stable figure object identifier such as A, AB, c1, or angle_mark_1.", "pattern": "^[A-Za-z][A-Za-z0-9_-]{0,31}$", "type": "string" }, "segmentEnd": { "description": "A stable figure object identifier such as A, AB, c1, or angle_mark_1.", "pattern": "^[A-Za-z][A-Za-z0-9_-]{0,31}$", "type": "string" }, "segmentStart": { "description": "A stable figure object identifier such as A, AB, c1, or angle_mark_1.", "pattern": "^[A-Za-z][A-Za-z0-9_-]{0,31}$", "type": "string" }, "to": { "description": "A stable figure object identifier such as A, AB, c1, or angle_mark_1.", "pattern": "^[A-Za-z][A-Za-z0-9_-]{0,31}$", "type": "string" }, "type": { "description": "Required fields depend on this assertion type. Call figure_get_capabilities for the matrix.", "enum": [ "collinearPoints", "parallel", "perpendicular", "equalLength", "pointOnLine", "pointOnCircle", "angleMeasure", "equalAngle", "angleBisected", "tangent", "pointOnSegment", "concurrent" ], "type": "string" }, "vertex": { "description": "A stable figure object identifier such as A, AB, c1, or angle_mark_1.", "pattern": "^[A-Za-z][A-Za-z0-9_-]{0,31}$", "type": "string" } }, "required": [ "type" ], "type": "object" }, "maxItems": 30, "type": "array" }, "canvas": { "additionalProperties": {}, "properties": { "height": { "default": 420, "maximum": 1200, "minimum": 120, "type": "integer" }, "viewBox": { "additionalProperties": {}, "properties": { "xMax": { "maximum": 100000, "minimum": -100000, "type": "number" }, "xMin": { "maximum": 100000, "minimum": -100000, "type": "number" }, "yMax": { "maximum": 100000, "minimum": -100000, "type": "number" }, "yMin": { "maximum": 100000, "minimum": -100000, "type": "number" } }, "required": [ "xMin", "xMax", "yMin", "yMax" ], "type": "object" }, "width": { "default": 640, "maximum": 1200, "minimum": 120, "type": "integer" } }, "type": "object" }, "objects": { "description": "Semantic objects. Each type has a conditional field contract in figure_get_capabilities.", "items": { "additionalProperties": {}, "properties": { "at": { "additionalProperties": {}, "properties": { "x": { "maximum": 100000, "minimum": -100000, "type": "number" }, "y": { "maximum": 100000, "minimum": -100000, "type": "number" } }, "required": [ "x", "y" ], "type": "object" }, "definition": { "additionalProperties": {}, "properties": { "at": { "additionalProperties": {}, "properties": { "x": { "maximum": 100000, "minimum": -100000, "type": "number" }, "y": { "maximum": 100000, "minimum": -100000, "type": "number" } }, "required": [ "x", "y" ], "type": "object" }, "center": { "description": "A stable figure object identifier such as A, AB, c1, or angle_mark_1.", "pattern": "^[A-Za-z][A-Za-z0-9_-]{0,31}$", "type": "string" }, "count": { "maximum": 3, "minimum": 1, "type": "integer" }, "dx": { "maximum": 2, "minimum": -2, "type": "number" }, "dy": { "maximum": 2, "minimum": -2, "type": "number" }, "end": { "description": "A stable figure object identifier such as A, AB, c1, or angle_mark_1.", "pattern": "^[A-Za-z][A-Za-z0-9_-]{0,31}$", "type": "string" }, "endAngleDegrees": { "maximum": 720, "minimum": -360, "type": "number" }, "from": { "description": "A stable figure object identifier such as A, AB, c1, or angle_mark_1.", "pattern": "^[A-Za-z][A-Za-z0-9_-]{0,31}$", "type": "string" }, "grid": { "type": "boolean" }, "kind": { "description": "Construction fields depend on this kind. Call figure_get_capabilities for the exact field matrix.", "enum": [ "midpointBetweenPoints", "intersection", "projection", "pointOnSegmentRatio", "triangleCenter", "betweenPoints", "throughPoints", "parallelThrough", "perpendicularThrough", "perpendicularBisector", "triangleMedian", "triangleAltitude", "fromThrough", "angleBisector", "centerRadius", "centerThroughPoint", "throughThreePoints", "diameter", "centerTangentToLine", "triangleIncircle", "centerRadiusAngles", "centerStartEnd", "threePoints", "onSegmentObject", "atPoint", "atCoordinate", "cartesian" ], "type": "string" }, "line": { "description": "A stable figure object identifier such as A, AB, c1, or angle_mark_1.", "pattern": "^[A-Za-z][A-Za-z0-9_-]{0,31}$", "type": "string" }, "mid": { "description": "A stable figure object identifier such as A, AB, c1, or angle_mark_1.", "pattern": "^[A-Za-z][A-Za-z0-9_-]{0,31}$", "type": "string" }, "objectA": { "description": "A stable figure object identifier such as A, AB, c1, or angle_mark_1.", "pattern": "^[A-Za-z][A-Za-z0-9_-]{0,31}$", "type": "string" }, "objectB": { "description": "A stable figure object identifier such as A, AB, c1, or angle_mark_1.", "pattern": "^[A-Za-z][A-Za-z0-9_-]{0,31}$", "type": "string" }, "onto": { "description": "A stable figure object identifier such as A, AB, c1, or angle_mark_1.", "pattern": "^[A-Za-z][A-Za-z0-9_-]{0,31}$", "type": "string" }, "point": { "description": "A stable figure object identifier such as A, AB, c1, or angle_mark_1.", "pattern": "^[A-Za-z][A-Za-z0-9_-]{0,31}$", "type": "string" }, "pointA": { "description": "A stable figure object identifier such as A, AB, c1, or angle_mark_1.", "pattern": "^[A-Za-z][A-Za-z0-9_-]{0,31}$", "type": "string" }, "pointB": { "description": "A stable figure object identifier such as A, AB, c1, or angle_mark_1.", "pattern": "^[A-Za-z][A-Za-z0-9_-]{0,31}$", "type": "string" }, "pointC": { "description": "A stable figure object identifier such as A, AB, c1, or angle_mark_1.", "pattern": "^[A-Za-z][A-Za-z0-9_-]{0,31}$", "type": "string" }, "points": { "items": { "description": "A stable figure object identifier such as A, AB, c1, or angle_mark_1.", "pattern": "^[A-Za-z][A-Za-z0-9_-]{0,31}$", "type": "string" }, "maxItems": 12, "minItems": 3, "type": "array" }, "radius": { "exclusiveMinimum": 0, "maximum": 100000, "type": "number" }, "ratio": { "maximum": 1, "minimum": 0, "type": "number" }, "segment": { "description": "A stable figure object identifier such as A, AB, c1, or angle_mark_1.", "pattern": "^[A-Za-z][A-Za-z0-9_-]{0,31}$", "type": "string" }, "side": { "enum": [ "internal", "external" ], "type": "string" }, "sideA": { "description": "A stable figure object identifier such as A, AB, c1, or angle_mark_1.", "pattern": "^[A-Za-z][A-Za-z0-9_-]{0,31}$", "type": "string" }, "sideB": { "description": "A stable figure object identifier such as A, AB, c1, or angle_mark_1.", "pattern": "^[A-Za-z][A-Za-z0-9_-]{0,31}$", "type": "string" }, "start": { "description": "A stable figure object identifier such as A, AB, c1, or angle_mark_1.", "pattern": "^[A-Za-z][A-Za-z0-9_-]{0,31}$", "type": "string" }, "startAngleDegrees": { "maximum": 360, "minimum": -360, "type": "number" }, "sweepDirection": { "enum": [ "clockwise", "counterclockwise" ], "type": "string" }, "text": { "maxLength": 80, "minLength": 1, "type": "string" }, "through": { "description": "A stable figure object identifier such as A, AB, c1, or angle_mark_1.", "pattern": "^[A-Za-z][A-Za-z0-9_-]{0,31}$", "type": "string" }, "tickStep": { "exclusiveMinimum": 0, "maximum": 1000, "type": "number" }, "to": { "description": "A stable figure object identifier such as A, AB, c1, or angle_mark_1.", "pattern": "^[A-Za-z][A-Za-z0-9_-]{0,31}$", "type": "string" }, "triangle": { "items": { "description": "A stable figure object identifier such as A, AB, c1, or angle_mark_1.", "pattern": "^[A-Za-z][A-Za-z0-9_-]{0,31}$", "type": "string" }, "maxItems": 3, "minItems": 3, "type": "array" }, "vertex": { "description": "A stable figure object identifier such as A, AB, c1, or angle_mark_1.", "pattern": "^[A-Za-z][A-Za-z0-9_-]{0,31}$", "type": "string" }, "which": { "additionalProperties": {}, "properties": { "index": { "maximum": 1, "minimum": 0, "type": "integer" }, "kind": { "enum": [ "nearPoint", "upper", "lower", "left", "right", "byIndex" ], "type": "string" }, "point": { "description": "A stable figure object identifier such as A, AB, c1, or angle_mark_1.", "pattern": "^[A-Za-z][A-Za-z0-9_-]{0,31}$", "type": "string" } }, "required": [ "kind" ], "type": "object" }, "xLabel": { "maxLength": 12, "minLength": 1, "type": "string" }, "yLabel": { "maxLength": 12, "minLength": 1, "type": "string" } }, "required": [ "kind" ], "type": "object" }, "id": { "description": "A stable figure object identifier such as A, AB, c1, or angle_mark_1.", "pattern": "^[A-Za-z][A-Za-z0-9_-]{0,31}$", "type": "string" }, "label": { "maxLength": 80, "minLength": 1, "type": "string" }, "radius": { "exclusiveMinimum": 0, "maximum": 1000, "type": "number" }, "size": { "exclusiveMinimum": 0, "maximum": 1000, "type": "number" }, "style": { "additionalProperties": {}, "properties": { "dash": { "enum": [ "solid", "dashed", "dotted" ], "type": "string" }, "fill": { "enum": [ "black", "gray", "lightGray", "red", "orange", "green", "blue", "purple", "white", "none" ], "type": "string" }, "opacity": { "maximum": 1, "minimum": 0.05, "type": "number" }, "stroke": { "enum": [ "black", "gray", "lightGray", "red", "orange", "green", "blue", "purple", "white", "none" ], "type": "string" }, "strokeWidth": { "maximum": 8, "minimum": 0.25, "type": "number" }, "textSize": { "maximum": 32, "minimum": 8, "type": "number" } }, "type": "object" }, "type": { "description": "Required and allowed fields depend on this type. Call figure_get_capabilities before authoring.", "enum": [ "point", "segment", "line", "ray", "circle", "arc", "polygon", "angleMark", "rightAngleMark", "tickMark", "label", "axes" ], "type": "string" } }, "required": [ "id", "type" ], "type": "object" }, "maxItems": 80, "minItems": 1, "type": "array" } }, "required": [ "objects" ], "type": "object" }, "kind": { "enum": [ "https_url", "base64_image", "rendered_figure" ], "type": "string" }, "mimeType": { "enum": [ "image/avif", "image/gif", "image/jpeg", "image/png", "image/svg+xml", "image/tiff", "image/webp" ], "type": "string" }, "url": { "format": "uri", "type": "string" } }, "required": [ "kind" ], "type": "object" }, "widthInCm": { "maximum": 20, "minimum": 1, "type": "number" } }, "required": [ "organizationId", "exerciseId", "figureType" ], "type": "object"}Output schema
Section titled “Output schema”{ "$schema": "https://json-schema.org/draft/2020-12/schema", "additionalProperties": false, "properties": { "figure": { "additionalProperties": false, "properties": { "exerciseFigureId": { "format": "uuid", "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$", "type": "string" }, "orderIndex": { "maximum": 9007199254740991, "minimum": 0, "type": "integer" }, "provenance": { "additionalProperties": false, "properties": { "byteLength": { "maximum": 104857600, "minimum": 0, "type": "integer" }, "createdBy": { "enum": [ "agent", "user", "import" ], "type": "string" }, "mimeType": { "maxLength": 100, "minLength": 1, "type": "string" }, "originalFileName": { "maxLength": 255, "minLength": 1, "type": "string" }, "pixelHeight": { "maximum": 100000, "minimum": 1, "type": "integer" }, "pixelWidth": { "maximum": 100000, "minimum": 1, "type": "integer" }, "renderQualityStatus": { "enum": [ "passed", "needs_revision", "unchecked" ], "type": "string" }, "renderSpecHash": { "pattern": "^[a-f0-9]{64}$", "type": "string" }, "sourceKind": { "enum": [ "local_file", "mcp_file", "https_url", "base64_image", "rendered_figure", "user_upload", "import", "unknown" ], "type": "string" } }, "required": [ "sourceKind", "createdBy" ], "type": "object" }, "rotationClockwiseDegrees": { "anyOf": [ { "const": 0, "type": "number" }, { "const": 90, "type": "number" }, { "const": 180, "type": "number" }, { "const": 270, "type": "number" } ] }, "type": { "enum": [ "text", "solution" ], "type": "string" }, "url": { "format": "uri", "type": "string" }, "widthInCm": { "maximum": 20, "minimum": 1, "type": "number" } }, "required": [ "type", "url", "widthInCm", "exerciseFigureId", "orderIndex", "rotationClockwiseDegrees" ], "type": "object" }, "receipt": { "additionalProperties": false, "properties": { "changedPaths": { "items": { "type": "string" }, "type": "array" }, "details": {}, "operation": { "enum": [ "copy_exercise", "copy_sheet", "update_exercise", "resolve_quality_issue", "dismiss_quality_issue", "update_sheet", "bulk_update_sheets", "append_exercises_to_sheet", "create_folder", "rename_folder", "delete_exercise", "delete_sheet", "delete_folder", "create_sheet", "create_exercise", "update_exercise_figure", "replace_exercise_figure", "remove_exercise_figure", "reorder_exercise_figures", "upload_exercise_figure", "set_exercise_visibility", "set_sheet_visibility" ], "type": "string" }, "precondition": { "additionalProperties": false, "properties": { "actualUpdatedAt": { "anyOf": [ { "minLength": 1, "type": "string" }, { "type": "null" } ] }, "expectedUpdatedAt": { "anyOf": [ { "minLength": 1, "type": "string" }, { "type": "null" } ] }, "status": { "enum": [ "matched", "not_required" ], "type": "string" } }, "required": [ "status" ], "type": "object" }, "resource": { "additionalProperties": false, "properties": { "id": { "format": "uuid", "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$", "type": "string" }, "type": { "enum": [ "exercise", "sheet", "folder" ], "type": "string" }, "url": { "format": "uri", "type": "string" } }, "required": [ "type", "id" ], "type": "object" }, "version": { "oneOf": [ { "additionalProperties": false, "properties": { "created": { "const": true, "type": "boolean" }, "resourceType": { "enum": [ "sheet", "exercise" ], "type": "string" }, "versionId": { "format": "uuid", "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$", "type": "string" }, "versionNumber": { "exclusiveMinimum": 0, "maximum": 9007199254740991, "type": "integer" } }, "required": [ "resourceType", "created", "versionId", "versionNumber" ], "type": "object" }, { "additionalProperties": false, "properties": { "created": { "const": false, "type": "boolean" }, "reason": { "minLength": 1, "type": "string" }, "resourceType": { "enum": [ "sheet", "exercise" ], "type": "string" } }, "required": [ "resourceType", "created", "reason" ], "type": "object" } ] }, "warnings": { "items": { "additionalProperties": false, "properties": { "code": { "type": "string" }, "details": {}, "message": { "type": "string" } }, "required": [ "code", "message" ], "type": "object" }, "type": "array" } }, "required": [ "resource", "operation", "changedPaths", "precondition", "warnings", "details" ], "type": "object" }, "review": { "additionalProperties": false, "properties": { "byteLength": { "maximum": 9007199254740991, "minimum": 0, "type": "integer" }, "nextActions": { "items": { "minLength": 1, "type": "string" }, "type": "array" }, "pixelHeight": { "anyOf": [ { "maximum": 9007199254740991, "minimum": 1, "type": "integer" }, { "type": "null" } ] }, "pixelWidth": { "anyOf": [ { "maximum": 9007199254740991, "minimum": 1, "type": "integer" }, { "type": "null" } ] }, "renderQualityStatus": { "anyOf": [ { "enum": [ "passed", "needs_revision", "unchecked" ], "type": "string" }, { "type": "null" } ] }, "sourceKind": { "enum": [ "local_file", "mcp_file", "https_url", "base64_image", "rendered_figure", "user_upload", "import", "unknown" ], "type": "string" }, "warnings": { "items": { "additionalProperties": false, "properties": { "code": { "minLength": 1, "type": "string" }, "details": {}, "message": { "minLength": 1, "type": "string" } }, "required": [ "code", "message" ], "type": "object" }, "type": "array" } }, "required": [ "pixelWidth", "pixelHeight", "byteLength", "sourceKind", "warnings", "renderQualityStatus", "nextActions" ], "type": "object" } }, "required": [ "figure", "review", "receipt" ], "type": "object"}