MCP 服务器

JobMojito

com.jobmojito/jobmojito
商业与运营 教育 公开且可连接 MCP 2025-11-25

此 MCP 可以做什么

Creates and manages AI-assisted interviews, simulated personas, coaching sessions, candidate registrations, interview results, and assessment reports.

create_catalogue_directory
Create coaching catalogue directory
[Coaching catalogue] Create a directory (page) in the coaching portal catalogue. A directory nests other directories (`tags_sub`), lists coaching sessions whose own `tags` match its `tags_interview_set_filter`, and can carry a fully custom Markdown page (`content_md`) with `[sessions]`, `[directory:…]`, `[session:…]` and `[plan-progress]` directives. Coaching-platform feature. Creates a directory (page) in the coaching portal catalogue. A directory nests other directories through `tags_sub`, lists coaching sessions through `tags_interview_set_filter`, and can replace the default grid with a custom Markdown page through `content_md`. The id you choose is the catalogue URL segment and cannot be changed afterwards.
可能执行破坏性操作 可访问外部资源
输入模式
{'type': 'object', 'required': ['id', 'name'], 'properties': {'id': {'type': ['string', 'null'], 'example': 'sales-coaching-en', 'pattern': '^[a-z0-9]+(?:(?:-|_)+[a-z0-9]+)*$', 'minLength': 1, 'description': 'Directory id â\x80\x94 also the catalogue URL segment (/catalogue/<id>) and the value other directories reference in their `tags_sub`. Lowercase letters, digits and single - or _ separators. Convention is to end language-specific directories with the language code, e.g. `sales-coaching-en`.'}, 'name': {'type': ['string', 'null'], 'example': 'Sales coaching', 'minLength': 1, 'description': 'Display name of the directory, shown as the page title and on its card.'}, 'status': {'enum': ['draft', 'active', 'archived', None], 'type': ['string', 'null'], 'example': 'active', 'description': 'Lifecycle status of the catalogue directory. Options â\x80\x94 `draft`: Not published â\x80\x94 the directory exists but is not served to visitors. | `active`: Published and served in the catalogue. | `archived`: Retired â\x80\x94 kept for reference but no longer served..'}, 'tags_sub': {'type': ['array', 'null'], 'items': {'type': 'string'}, 'example': ['sales-coaching-objections-en', 'sales-coaching-closing-en'], 'description': 'Ids of the directories nested under this one, in display order. Replaces the whole list â\x80\x94 send the full set, not just the additions. A referenced directory only appears if it exists and is visible to the viewer.'}, 'coach_plan': {'enum': ['demo', 'screening', '2nd', '3rd', 'closing', 'job-specific', 'other', None], 'type': ['string', 'null'], 'example': 'screening', 'description': 'Coaching-plan stage this item belongs to, used by the coaching-plan progress view. Omit/null to leave it out of any plan. Options â\x80\x94 `demo`: Demo session. | `screening`: Screening-interview practice. | `2nd`: Second-interview practice. | `3rd`: Third-interview practice. | `closing`: Closing / salary-negotiation practice. | `job-specific`: Job-specific coaching. | `other`: Anything that does not fit the other buckets..'}, 'content_md': {'type': ['string', 'null'], 'example': '## Sales coaching\n\nPick a session to practise with.\n\n[chip:6 sessions] [chip:Beginner,tone=accent]\n\n[sessions:filter=objection-handling,limit=6]\n', 'description': "Markdown for a custom directory page. When set (even as an empty string) the markdown replaces the default grid and decides the layout itself; null renders the plain grid of sub-directories and sessions. Alongside normal Markdown you can place these directives, each ALONE on its own line: `[plan-progress]` (the learner's coaching-plan progress), `[directory:<tag-id>]` (a card for one sub-directory), `[session:<interview-id>]` (a card for one session), `[sessions]` (every session in this directory), `[sessions:<term>]` (sessions matching a term), `[sessions:filter=<term>,limit=<n>]` (a filtered, capped list). A directive on a line with other text is rendered as ordinary text. Chips, callouts, cards, columns and buttons are available here too â\x80\x94 full vocabulary: https://developer.jobmojito.com/cookbooks/format-content-with-markdown"}, 'parent_tag': {'type': ['string', 'null'], 'example': 'home-employee-en', 'description': "Id of an existing directory to nest this new one under: the new id is appended to that directory's `tags_sub`. Omit to create a top-level directory (reachable via a direct link, or by adding it to another directory later)."}, 'visibility': {'enum': ['public', 'merchant_public', 'merchant_invite', 'merchant_unlisted', None], 'type': ['string', 'null'], 'example': 'merchant_public', 'description': "Who can see the catalogue directory. Options â\x80\x94 `public`: Shared across every merchant. Platform admins only â\x80\x94 a merchant caller is rejected by row-level security. | `merchant_public`: Listed in the merchant's own catalogue â\x80\x94 the normal choice. | `merchant_invite`: Owned by the merchant but not listed; reachable only for invited users. | `merchant_unlisted`: Owned by the merchant but not listed; reachable only via a direct link.."}, 'description': {'type': ['string', 'null'], 'example': 'Practice discovery, objection handling and closing.', 'description': 'Short description shown on the directory card.'}, 'merchant_id': {'type': ['string', 'null'], 'example': '28106cba-1c27-4e53-b149-32113e5e8e31', 'description': 'Merchant that owns the directory. Admin / sub-merchant callers only; otherwise taken from your token.'}, 'conversation_id': {'type': 'string', 'description': "Pass the exact conversation_id from the server's previous response, unchanged. The server provides it on the first call â\x80\x94 never invent one, and do not issue parallel tool calls until you have it. Keep passing the same conversation_id for the rest of the conversation, including after later user messages or on a different task; do not reset it when the user starts a new request."}, 'cover_image_url': {'type': ['string', 'null'], 'description': 'Cover image URL shown on the directory card.'}, 'mojito_language_code': {'enum': ['ar', 'bg', 'zh', 'hr', 'cs', 'da', 'nl', 'en', 'fil', 'fi', 'fr', 'de', 'el', 'hi', 'hu', 'id', 'it', 'ja', 'ko', 'ms', 'no', 'pl', 'pt', 'br', 'ro', 'ru', 'sk', 'es', 'sv', 'ta', 'th', 'tr', 'uk', 'vi', None], 'type': ['string', 'null'], 'example': 'en', 'description': 'Language of the directory (one of the platform-languages.json codes). The catalogue groups directories by language; defaults to `en` when omitted.'}, 'tags_interview_set_filter': {'type': ['array', 'null'], 'items': {'type': 'string'}, 'example': ['sales', 'objection-handling'], 'description': 'Tag filter selecting which coaching sessions this directory lists: a session appears when its own `tags` contain EVERY tag here (an AND, not an OR). Only `active` coaching/persona sessions with visibility `public` or `merchant_public` are listed. Set the matching tags on the session with the create-interview / job-interview-update `tags` field.'}}}
输出模式
{'type': 'object', 'required': ['id', 'merchant_id', 'parent_tag', 'catalogue_url'], 'properties': {'id': {'type': ['string', 'null'], 'example': 'sales-coaching-en', 'description': 'Id of the created directory.'}, 'parent_tag': {'type': ['string', 'null'], 'description': 'The directory this one was nested under, when `parent_tag` was supplied.'}, 'merchant_id': {'type': ['string', 'null'], 'description': 'Owning merchant id. Null for a platform-wide (`public`) directory.'}, 'catalogue_url': {'type': ['string', 'null'], 'example': 'https://coaching.example.com/catalogue/sales-coaching-en', 'description': 'Public URL of the directory page, when the merchant has a coaching-portal domain configured. Null otherwise.'}, '_mcp_instructions': {'type': 'object', 'properties': {'conversation_id': {'type': 'string', 'description': 'The server-issued conversation identifier.'}}, 'description': 'Server-issued metadata for this conversation.'}}, 'description': 'The created catalogue directory.', 'x-fastmcp-top-level-schema': 'CatalogueTagCreateResponse'}
create_interview
Create interview
[Interviews] Create a new interview and auto-generate its question sequence from position data. The `interview_template_id` you pass also sets the modality (voice-only vs realtime/pre-recorded avatar) — see `list_avatars`. Creates a new interview / coaching / assessment definition, generates its description, questions and candidate expectations via AI, and provisions default steps. Optionally provisions an embed key.
可能执行破坏性操作 可访问外部资源
输入模式
{'type': 'object', 'required': ['name', 'location', 'interview_template_id', 'mojito_language_code', 'status', 'type', 'visibility'], 'properties': {'code': {'type': ['string', 'null'], 'example': 'my code', 'description': 'Optional external code/reference for the interview.'}, 'name': {'type': ['string', 'null'], 'example': 'Project manager', 'minLength': 1, 'description': 'Interview / position name.'}, 'tags': {'type': ['array', 'null'], 'items': {'type': 'string'}, 'example': ['interview-practice', 'sales'], 'description': "Free-form tags stored on the interview. Tags are also the coaching-catalogue mapping key: a catalogue directory (see the catalogue-tag-create / catalogue-tag-update endpoints) lists a coaching or persona session when the session's tags contain EVERY tag in that directory's `tags_interview_set_filter`. Only `active` sessions with visibility `public` or `merchant_public` are listed."}, 'type': {'enum': ['interview', 'coaching', 'assessment', None], 'type': ['string', 'null'], 'example': 'interview', 'description': 'Product type of the interview. Options â\x80\x94 `interview`: Standard candidate interview for a role â\x80\x94 answers are AI-scored and produce a hiring recommendation. | `coaching`: Practice/coaching session â\x80\x94 candidate-facing feedback to help them improve; not a hiring evaluation. Only available on the coaching portal, NOT the interview portal. | `assessment`: Skills/knowledge assessment â\x80\x94 evaluates competencies and is scored like an interview..'}, 'status': {'enum': ['draft', 'active', None], 'type': ['string', 'null'], 'example': 'active', 'description': 'Lifecycle status of the interview. Options â\x80\x94 `draft`: Created but not published â\x80\x94 not visible to candidates and cannot be run yet. Use to stage an interview before going live. | `active`: Published and live â\x80\x94 candidates can run it..'}, 'location': {'type': ['string', 'null'], 'example': 'remote', 'minLength': 1, 'description': 'Job location â\x80\x94 a city/country, or `remote`. Required and must not be empty: when the job description gives no location, pass `Not specified`.'}, 'recording': {'enum': ['audio_first_5_answers', 'audio_all', 'video_all', 'video_first_5_answers', None], 'type': ['string', 'null'], 'example': 'video_all', 'description': 'Cheating/proctoring detection mode for candidate answers â\x80\x94 this is NOT a full session recording. Video options also record the candidate. Omit/null to disable. Options â\x80\x94 `audio_first_5_answers`: Audio-only cheating detection, first 5 answers only. | `audio_all`: Audio-only cheating detection on every answer. | `video_all`: Audio + video cheating detection on every answer (candidate is recorded for all answers). | `video_first_5_answers`: Audio + video cheating detection, first 5 answers only..'}, 'visibility': {'enum': ['merchant_public', 'merchant_invite', 'merchant_unlisted', None], 'type': ['string', 'null'], 'example': 'merchant_public', 'description': "Who can discover and access the interview. Options â\x80\x94 `merchant_public`: Listed on the merchant's public interview list â\x80\x94 anyone with the merchant link can find and start it. | `merchant_invite`: Invite-only â\x80\x94 only candidates explicitly invited (by email/link) can access it; not listed anywhere. | `merchant_unlisted`: Reachable only via a direct link â\x80\x94 not listed anywhere; share the link manually.."}, 'description': {'type': ['string', 'null'], 'example': 'Backend role focused on Python, async APIs, and AWS.', 'description': 'Short, two-sentence job description shown to the candidate. Provide it to use it as-is; leave it null/blank and it is AI-generated from the position name and any other context.'}, 'environment': {'enum': ['production', 'uat', 'development', 'demo', None], 'type': ['string', 'null'], 'example': 'production', 'description': 'Which of your webhook environments results from this interview are delivered to. Defaults to production. Options â\x80\x94 `production`: Live hiring. Results reach the webhooks configured as production. This is the default when the field is omitted. | `uat`: User-acceptance testing - an isolated environment for pre-release verification. | `development`: Development/testing. Use for interviews created by a test or preview app so their results never reach the production webhook. | `demo`: Demonstrations and sales trials..'}, 'is_embedded': {'type': ['boolean', 'null'], 'example': False, 'description': 'Set true when the interview will be embedded as an iframe on an external page. Provisions an embed key and returns embed_id / embed_signing_key, which are used to authenticate/sign the iframe embed.'}, 'merchant_id': {'type': ['string', 'null'], 'example': '28106cba-1c27-4e53-b149-32113e5e8e31', 'description': 'Merchant id. Admin / sub-merchant callers only; otherwise taken from your token.'}, 'result_view': {'enum': ['none', 'minimal', 'minimal_with_score', 'advanced', 'full', 'full_expand_scores', None], 'type': ['string', 'null'], 'example': 'full', 'description': 'Result screen shown to the candidate after finishing. With any value other than `none`, the candidate sees a results screen where they can provide feedback, record an intro video and edit the transcript, and must then submit the result; the value sets how much score/result detail is shown. Options â\x80\x94 `none`: No results screen at all â\x80\x94 the interview is submitted immediately when the candidate finishes (no feedback, intro video, transcript edit or manual submit step). | `minimal`: Minimal results layout, no score shown. | `minimal_with_score`: Minimal results layout including the overall score. | `advanced`: Advanced results layout with more detail. | `full`: Full results layout with all sections. | `full_expand_scores`: Full results with every score breakdown expanded..'}, 'max_duration': {'type': ['number', 'null'], 'example': 1200, 'description': 'Maximum interview duration in seconds. Scopes how many questions are generated (see interview_length) and is stored on the interview as the live session limit and the basis for the credit multiplier. Defaults to 1200 (20 minutes) when omitted.'}, 'max_followups': {'type': ['integer', 'null'], 'example': 2, 'maximum': 999.0, 'minimum': 0.0, 'description': 'Maximum number of AI follow-up questions. 0 disables follow-ups; presets are 0-3 (none/low/normal/high) and custom values start at 4; null uses the template default (Normal).'}, 'custom_scoring': {'type': ['object', 'null'], 'description': 'Custom result-scoring overrides merged with defaults and template overrides.', 'additionalProperties': {}}, 'interview_tone': {'enum': ['relaxed', 'simple', 'professional', 'persuasive', 'exact', None], 'type': ['string', 'null'], 'example': 'professional', 'description': "Interview tone â\x80\x94 configures the AI avatar's speaking style and the tone of the AI-generated questions and follow-ups. Case-insensitive; omit to default to relaxed. Options â\x80\x94 `relaxed`: Friendly and conversational tone that helps candidates feel at ease. | `simple`: Plain language at CEFR A2 level â\x80\x94 short sentences and simple words. | `professional`: Formal and business-like approach suitable for senior roles. | `persuasive`: Engaging style that encourages candidates to elaborate. | `exact`: Asks the questions exactly as provided, without rephrasing â\x80\x94 for interviews built from your own questions (create_interview_from_questions) where the wording is a script.."}, 'interview_type': {'enum': ['pre-screening', 'pre-screening-with-test-questions', 'second-interview', 'remote-freelancer-verification', 'strength-based-interview', 'potential-based-interview', 'process-verification-from-knowledge-base', None], 'type': ['string', 'null'], 'example': 'pre-screening-with-test-questions', 'description': 'Interview style â\x80\x94 configures the AI avatar and shapes both the AI-generated questions and the follow-up questions asked during the interview. Defaults to pre-screening when omitted. Options â\x80\x94 `pre-screening`: Pre-screening â\x80\x94 quick qualification check focusing on basic requirements and availability. | `pre-screening-with-test-questions`: Pre-screening with test questions â\x80\x94 pre-screening plus practical questions to test relevant skills. | `second-interview`: Second round interview â\x80\x94 deeper dive for candidates who passed initial screening. | `remote-freelancer-verification`: Remote worker verification â\x80\x94 verify remote work capabilities and communication skills. | `strength-based-interview`: Strength-based interview â\x80\x94 focus on what candidates enjoy and excel at to predict job satisfaction. | `potential-based-interview`: Potential-based interview â\x80\x94 assess learning ability and growth potential rather than past experience. | `process-verification-from-knowledge-base`: Knowledge Base interview â\x80\x94 generate questions from your knowledge base documents..'}, 'conversation_id': {'type': 'string', 'description': "Pass the exact conversation_id from the server's previous response, unchanged. The server provides it on the first call â\x80\x94 never invent one, and do not issue parallel tool calls until you have it. Keep passing the same conversation_id for the rest of the conversation, including after later user messages or on a different task; do not reset it when the user starts a new request."}, 'cover_image_url': {'type': ['string', 'null'], 'example': 'https://example.com/cover.png', 'description': 'Cover image URL.'}, 'seniority_level': {'enum': ['entry-level', 'intermediate', 'senior', 'managerial', 'director', 'executive', None], 'type': ['string', 'null'], 'example': 'senior', 'description': 'Target seniority level for the role; auto-detected from the job description when omitted. Options â\x80\x94 `entry-level`: Early-career or graduate roles. | `intermediate`: Some experience required. | `senior`: Experienced professional. | `managerial`: Team or department lead. | `director`: Director-level responsibility. | `executive`: C-suite or executive role..'}, 'welcome_message': {'type': ['string', 'null'], 'description': 'Custom welcome message shown to the candidate.'}, 'description_long': {'type': ['string', 'null'], 'description': 'Full job description in Markdown (Job Purpose, Responsibilities, Required & Preferred Qualifications). Provide it to use it as-is; leave it null/blank and it is AI-generated (interview and assessment types only). Rendered as Markdown on the candidate-facing position page, including chips, callouts, cards, columns and buttons â\x80\x94 formatting guide: https://developer.jobmojito.com/cookbooks/format-content-with-markdown'}, 'interview_length': {'anyOf': [{'type': 'number'}, {'type': 'string'}, {}], 'example': 8, 'description': 'Number of questions to generate (1-40). Also capped by max_duration, which allows one question per 2 minutes: 20 min -> 10 questions, 30 min -> 15, 45 min -> 22, 60 min -> 30, 80 min -> 40. Asking for more than the cap is not an error â\x80\x94 you get the cap, and the response reports the real count in questions_generated. Omit this field to let the AI pick 5-8.'}, 'interview_salary': {'type': ['string', 'null'], 'example': '$80k - $100k', 'description': 'Salary range shown for the position.'}, 'thank_you_message': {'type': ['string', 'null'], 'description': 'Custom thank-you message shown after the interview.'}, 'additional_context': {'type': ['object', 'null'], 'description': 'Arbitrary additional context object merged into AI generation.', 'additionalProperties': {}}, 'hiring_for_company': {'type': ['object', 'null'], 'example': {'name': 'undisclosed'}, 'properties': {'name': {'type': ['string', 'null'], 'example': 'Unimo Enterprises', 'description': "End-employer name. Omit/null when hiring for yourself, 'undisclosed' for an unnamed external client, or the client's company name."}, 'sector': {'type': ['string', 'null'], 'example': 'Logistics and Supply Chain', 'description': 'Industry / sector of the end employer.'}, 'location': {'type': ['string', 'null'], 'example': 'Sri Lanka', 'description': 'Primary location of the end employer.'}, 'description': {'type': ['string', 'null'], 'example': 'Unimo Enterprises is a leading logistics and supply chain solutions provider.', 'description': 'Short description of the end employer, used as background context by the agent.'}, 'company_size': {'type': ['string', 'null'], 'example': '100-200', 'description': 'Approximate headcount of the end employer.'}}, 'description': "Who the position is really for. Omit/null (or an object with name null/blank) when hiring for yourself; { name: 'undisclosed' } for an unnamed external client; or { name: '<company>' } plus optional description/location/sector/company_size for a named client. Stored in creation_parameters.hiring_for_company."}, 'interview_attempts': {'type': ['number', 'null'], 'example': 1, 'maximum': 20.0, 'minimum': 1.0, 'description': 'Allowed candidate attempts (1-20).'}, 'instructional_video': {'type': ['boolean', 'null'], 'example': True, 'description': 'Show an instructional video before approval. Defaults to false.'}, 'interview_department': {'type': ['string', 'null'], 'example': 'Engineering', 'description': 'Department the position belongs to.'}, 'mojito_language_code': {'enum': ['ar', 'bg', 'zh', 'hr', 'cs', 'da', 'nl', 'en', 'fil', 'fi', 'fr', 'de', 'el', 'hi', 'hu', 'id', 'it', 'ja', 'ko', 'ms', 'no', 'pl', 'pt', 'br', 'ro', 'ru', 'sk', 'es', 'sv', 'ta', 'th', 'tr', 'uk', 'vi', None], 'type': ['string', 'null'], 'example': 'en', 'description': 'Platform language code used for the interview. Must be one of the platform-languages.json codes.'}, 'recruiter_profile_id': {'type': ['string', 'null'], 'example': '28106cba-1c27-4e53-b149-32113e5e8e31', 'description': 'Profile id of the recruiter owning this interview. Must be a merchant/merchant_owner/admin profile of the same merchant.'}, 'interview_template_id': {'type': ['string', 'null'], 'format': 'uuid', 'example': 'baa3bf7c-6926-46fd-9005-16738a31f72d', 'minLength': 1, 'description': 'Id of the interview template to base this interview on.'}, 'candidate_expectations': {'type': ['string', 'null'], 'description': 'Free-text candidate expectations folded into AI generation.'}, 'include_closing_prompt': {'type': ['boolean', 'null'], 'example': True, 'description': 'Include a closing prompt. Defaults to true.'}, 'pdf_export_auto_config': {'type': ['object', 'null'], 'properties': {'files': {'type': ['boolean', 'null'], 'description': 'Include uploaded candidate files.'}, 'template': {'enum': ['classic', 'modern', 'one_pager', None], 'type': ['string', 'null'], 'description': 'Report layout: classic, modern, or one_pager. Omit for the merchant default (modern when unset).'}, 'analytics': {'type': ['boolean', 'null'], 'description': 'Include analytics.'}, 'transcript': {'type': ['boolean', 'null'], 'description': 'Include the interview transcript.'}, 'contact_details': {'type': ['boolean', 'null'], 'description': 'Include candidate contact details.'}, 'answer_recording': {'type': ['boolean', 'null'], 'description': 'Include per-answer recordings.'}, 'ai_scoring_rubric': {'type': ['boolean', 'null'], 'description': 'Include the AI scoring rubric.'}, 'group_by_question': {'type': ['boolean', 'null'], 'description': 'Group transcript answers by expected question.'}, 'session_recording': {'type': ['boolean', 'null'], 'description': 'Include the full-session recording.'}, 'mojito_language_code': {'enum': ['ar', 'bg', 'zh', 'hr', 'cs', 'da', 'nl', 'en', 'fil', 'fi', 'fr', 'de', 'el', 'hi', 'hu', 'id', 'it', 'ja', 'ko', 'ms', 'no', 'pl', 'pt', 'br', 'ro', 'ru', 'sk', 'es', 'sv', 'ta', 'th', 'tr', 'uk', 'vi', None], 'type': ['string', 'null'], 'example': 'en', 'description': 'Report language code (a platform-languages.json code).'}, 'ai_recruiter_assessment': {'type': ['boolean', 'null'], 'description': 'Include the AI recruiter assessment.'}}, 'description': 'Auto-generate a candidate PDF report with these options once the interview completes. null disables auto-export.'}, 'recording_full_session': {'enum': ['audio_all', 'video_all', None], 'type': ['string', 'null'], 'example': 'video_all', 'description': 'Full interview-session recording (includes the avatar and voice) produced as a single file. Independent of `recording`. Omit/null to disable. Options â\x80\x94 `audio_all`: Record the whole session audio (avatar + candidate voice) into a single file. Adds +0.2 credits. | `video_all`: Record the whole session video + audio (avatar + candidate) into a single file. Adds +0.4 credits..'}, 'required_pronunciation': {'type': ['boolean', 'null'], 'example': False, 'description': 'Require pronunciation assessment (restricts to pronunciation-capable languages). Defaults to false.'}, 'knowledge_base_store_id': {'type': ['string', 'null'], 'description': 'Knowledge base store id to source additional context from.'}, 'questions_random_subset': {'type': ['number', 'null'], 'example': 0.5, 'maximum': 0.9, 'minimum': 0.01, 'description': 'Ask only a random subset of the questions, expressed as a fraction between 0.01 and 0.9 (e.g. 0.5 = 50%). null asks all questions.'}, 'include_rapport_question': {'type': ['boolean', 'null'], 'example': True, 'description': 'Include an opening rapport question. Defaults to false.'}, 'interview_available_till': {'type': ['string', 'null'], 'example': '2026-12-31', 'description': 'ISO date/time after which the interview is no longer available to candidates. null keeps it always available.'}, 'use_enhanced_expectations': {'type': ['boolean', 'null'], 'description': 'Reserved flag passed through to generation.'}, 'candidate_video_introduction': {'enum': ['optional', 'required', None], 'type': ['string', 'null'], 'example': 'optional', 'description': 'Whether a candidate video introduction is optional or required.'}, 'interview_conversation_speed': {'enum': ['slower', 'normal', 'faster', None], 'type': ['string', 'null'], 'example': 'normal', 'description': 'Conversation pace of the AI avatar. Omit/null keeps the template default pace. Options â\x80\x94 `slower`: The avatar speaks more slowly â\x80\x94 easier to follow for non-native speakers. | `normal`: Default speaking pace. | `faster`: The avatar speaks more quickly for a snappier conversation..'}, 'result_enable_edit_transcript': {'type': ['boolean', 'null'], 'example': True, 'description': 'Allow editing the transcript on the result view. Defaults to true.'}, 'instructional_video_custom_text': {'type': ['string', 'null'], 'description': 'Custom narration text for the instructional video.'}}}
输出模式
{'type': 'object', 'required': ['interview_def_set_id', 'questions_generated', 'max_duration'], 'properties': {'embed_id': {'type': ['string', 'null'], 'description': 'Embed id, present only when is_embedded=true.'}, 'max_duration': {'type': ['number', 'null'], 'example': 1200, 'description': 'Live session limit in seconds stored on the interview â\x80\x94 the value sent, or the 1200 default when omitted.'}, '_mcp_instructions': {'type': 'object', 'properties': {'conversation_id': {'type': 'string', 'description': 'The server-issued conversation identifier.'}}, 'description': 'Server-issued metadata for this conversation.'}, 'embed_signing_key': {'type': ['string', 'null'], 'description': 'Embed signing key, present only when is_embedded=true.'}, 'questions_generated': {'type': ['number', 'null'], 'example': 8, 'description': 'Number of questions actually generated. May be lower than the requested interview_length, which is capped by max_duration.'}, 'interview_def_set_id': {'type': ['string', 'null'], 'example': '00000000-0000-0000-0000-000000000000', 'description': 'Id of the newly created interview definition set.'}}, 'description': 'Id of the created interview, the number of questions generated and the stored max_duration. Includes embed_id/embed_signing_key when is_embedded=true.', 'x-fastmcp-top-level-schema': 'JobInterviewCreateResponse'}
create_interview_from_questions
Create interview from questions
[Interviews] Create a new interview from an explicit array of questions. The AI rephrases your wording by default; pass `interview_tone="exact"` to have each question asked verbatim, which is what you want when the wording is a script (compliance, translated, or legally reviewed text). Creates a new interview definition set from a caller-provided array of questions, builds its default and generated steps, optionally activates it, and optionally creates an embed key.
可能执行破坏性操作 可访问外部资源
输入模式
{'type': 'object', 'required': ['name', 'location', 'interview_template_id', 'mojito_language_code', 'description', 'status', 'type', 'visibility', 'questions'], 'properties': {'code': {'type': ['string', 'null'], 'description': 'Optional external code/reference.'}, 'name': {'type': ['string', 'null'], 'example': 'Project manager', 'minLength': 1, 'description': 'Interview/position name.'}, 'tags': {'type': ['array', 'null'], 'items': {'type': 'string'}, 'example': ['interview-practice', 'sales'], 'description': "Free-form tags stored on the interview. Tags are also the coaching-catalogue mapping key: a catalogue directory (see the catalogue-tag-create / catalogue-tag-update endpoints) lists a coaching or persona session when the session's tags contain EVERY tag in that directory's `tags_interview_set_filter`. Only `active` sessions with visibility `public` or `merchant_public` are listed."}, 'type': {'enum': ['interview', 'coaching', 'assessment', None], 'type': ['string', 'null'], 'example': 'interview', 'description': 'Product type of the interview. Options â\x80\x94 `interview`: Standard candidate interview for a role â\x80\x94 answers are AI-scored and produce a hiring recommendation. | `coaching`: Practice/coaching session â\x80\x94 candidate-facing feedback to help them improve; not a hiring evaluation. Only available on the coaching portal, NOT the interview portal. | `assessment`: Skills/knowledge assessment â\x80\x94 evaluates competencies and is scored like an interview..'}, 'status': {'enum': ['draft', 'active', None], 'type': ['string', 'null'], 'example': 'active', 'description': 'Lifecycle status of the interview. Options â\x80\x94 `draft`: Created but not published â\x80\x94 not visible to candidates and cannot be run yet. Use to stage an interview before going live. | `active`: Published and live â\x80\x94 candidates can run it..'}, 'location': {'type': ['string', 'null'], 'example': 'remote', 'minLength': 1, 'description': 'Job location â\x80\x94 a city/country, or `remote`. Required and must not be empty: when the job description gives no location, pass `Not specified`.'}, 'questions': {'type': ['array', 'null'], 'items': {'type': 'object', 'required': ['question'], 'properties': {'id': {'type': ['string', 'null'], 'description': "Identifier for this question. job-interview-get returns the question's real id here; send it back to job-interview-update so an unchanged question keeps its existing record (and with it its answer rules and any rendered avatar video). Also the handle another question references via conditional_question_main_id. On job-interview-create-from-array it is a caller-local value, only needed for those references."}, 'label': {'type': ['string', 'null'], 'description': 'Optional label/tag stored on the question.'}, 'duration': {'type': ['number', 'null'], 'description': 'Answer duration in seconds for this question.'}, 'question': {'type': ['string', 'null'], 'description': 'The question text shown to the candidate.'}, 'is_expert': {'type': ['boolean', 'null'], 'description': "Expert listening question (view 'with listening expert')."}, 'external_id': {'type': ['string', 'null'], 'description': 'External identifier stored on the question. job-interview-update matches on this first, so an ATS that owns stable ids can send its own array and have the diff line up without round-tripping our ids.'}, 'external_data': {'type': ['object', 'null'], 'description': 'Arbitrary JSON metadata stored on the question.', 'additionalProperties': {}}, 'is_conditional': {'type': ['boolean', 'null'], 'description': "Conditional follow-up question (view 'with listening conditional'). Use with conditional_question_main_id."}, 'knowledge_base_id': {'type': ['string', 'null'], 'description': 'Knowledge-base store id (uuid) the question draws context from.'}, 'is_multiple_choice': {'type': ['boolean', 'null'], 'description': "Multiple-choice question (view 'multiple choice')."}, 'is_without_scoring': {'type': ['boolean', 'null'], 'description': "Question is asked but not scored (view 'without scoring')."}, 'mojito_language_code': {'enum': ['ar', 'bg', 'zh', 'hr', 'cs', 'da', 'nl', 'en', 'fil', 'fi', 'fr', 'de', 'el', 'hi', 'hu', 'id', 'it', 'ja', 'ko', 'ms', 'no', 'pl', 'pt', 'br', 'ro', 'ru', 'sk', 'es', 'sv', 'ta', 'th', 'tr', 'uk', 'vi', None], 'type': ['string', 'null'], 'example': 'en', 'description': 'Per-question language override (one of the platform-languages.json codes). Inherits the interview language when omitted.'}, 'question_alternatives': {'type': ['array', 'null'], 'items': {'type': 'string'}, 'description': 'Alternative phrasings for the question.'}, 'candidate_expectations_json': {'type': ['object', 'null'], 'properties': {'weak': {'type': ['array', 'null'], 'items': {'type': 'string'}, 'description': 'Baseline requirements every viable candidate should meet (table stakes).'}, 'strong': {'type': ['array', 'null'], 'items': {'type': 'string'}, 'description': 'High-bar requirements only standout candidates clear.'}, 'moderate': {'type': ['array', 'null'], 'items': {'type': 'string'}, 'description': 'Requirements expected of a solid, competent candidate.'}}, 'description': 'Per-question candidate expectations, bucketed by requirement level (weak/moderate/strong). Extra keys are preserved.'}, 'conditional_question_main_id': {'type': ['string', 'null'], 'description': 'For a conditional question, the id (the "id" field above) of the parent question in this same array that triggers it. The parent must appear earlier in the array than the conditional question referencing it.'}, 'is_candidate_asking_recruiter': {'type': ['boolean', 'null'], 'description': "Candidate-asks-recruiter prompt (view 'candidate asking recruiter')."}}, 'additionalProperties': {}}, 'minItems': 1, 'description': 'Ordered list of interview questions to create as steps.'}, 'recording': {'enum': ['audio_first_5_answers', 'audio_all', 'video_all', 'video_first_5_answers', None], 'type': ['string', 'null'], 'example': 'video_all', 'description': 'Cheating/proctoring detection mode for candidate answers â\x80\x94 this is NOT a full session recording. Video options also record the candidate. Omit/null to disable. Options â\x80\x94 `audio_first_5_answers`: Audio-only cheating detection, first 5 answers only. | `audio_all`: Audio-only cheating detection on every answer. | `video_all`: Audio + video cheating detection on every answer (candidate is recorded for all answers). | `video_first_5_answers`: Audio + video cheating detection, first 5 answers only..'}, 'visibility': {'enum': ['merchant_public', 'merchant_invite', 'merchant_unlisted', None], 'type': ['string', 'null'], 'example': 'merchant_public', 'description': "Who can discover and access the interview. Options â\x80\x94 `merchant_public`: Listed on the merchant's public interview list â\x80\x94 anyone with the merchant link can find and start it. | `merchant_invite`: Invite-only â\x80\x94 only candidates explicitly invited (by email/link) can access it; not listed anywhere. | `merchant_unlisted`: Reachable only via a direct link â\x80\x94 not listed anywhere; share the link manually.."}, 'description': {'type': ['string', 'null'], 'example': 'Project manager role', 'minLength': 1, 'description': 'Short interview description.'}, 'environment': {'enum': ['production', 'uat', 'development', 'demo', None], 'type': ['string', 'null'], 'example': 'production', 'description': 'Which of your webhook environments results from this interview are delivered to. Defaults to production. Options â\x80\x94 `production`: Live hiring. Results reach the webhooks configured as production. This is the default when the field is omitted. | `uat`: User-acceptance testing - an isolated environment for pre-release verification. | `development`: Development/testing. Use for interviews created by a test or preview app so their results never reach the production webhook. | `demo`: Demonstrations and sales trials..'}, 'is_embedded': {'type': ['boolean', 'null'], 'description': 'Set true when the interview will be embedded as an iframe on an external page. Creates an embed key and returns embed_id/embed_signing_key, used to authenticate/sign the iframe embed.'}, 'merchant_id': {'type': ['string', 'null'], 'description': 'Target merchant id (admins / sub-merchant only).'}, 'result_view': {'enum': ['none', 'minimal', 'minimal_with_score', 'advanced', 'full', 'full_expand_scores', None], 'type': ['string', 'null'], 'example': 'full', 'description': 'Result screen shown to the candidate after finishing. With any value other than `none`, the candidate sees a results screen where they can provide feedback, record an intro video and edit the transcript, and must then submit the result; the value sets how much score/result detail is shown. Options â\x80\x94 `none`: No results screen at all â\x80\x94 the interview is submitted immediately when the candidate finishes (no feedback, intro video, transcript edit or manual submit step). | `minimal`: Minimal results layout, no score shown. | `minimal_with_score`: Minimal results layout including the overall score. | `advanced`: Advanced results layout with more detail. | `full`: Full results layout with all sections. | `full_expand_scores`: Full results with every score breakdown expanded..'}, 'max_followups': {'type': ['integer', 'null'], 'example': 2, 'maximum': 999.0, 'minimum': 0.0, 'description': 'Maximum number of AI follow-up questions. 0 disables follow-ups; presets are 0-3 (none/low/normal/high) and custom values start at 4; null uses the template default (Normal).'}, 'custom_scoring': {'type': ['object', 'null'], 'description': 'Custom scoring overrides merged with defaults.', 'additionalProperties': {}}, 'interview_tone': {'enum': ['relaxed', 'simple', 'professional', 'persuasive', 'exact', None], 'type': ['string', 'null'], 'example': 'professional', 'description': "Tone â\x80\x94 configures the AI avatar's speaking style and the follow-up questions it generates; the base `questions` you supply are not affected. Case-insensitive; omit to default to relaxed. Options â\x80\x94 `relaxed`: Friendly and conversational tone that helps candidates feel at ease. | `simple`: Plain language at CEFR A2 level â\x80\x94 short sentences and simple words. | `professional`: Formal and business-like approach suitable for senior roles. | `persuasive`: Engaging style that encourages candidates to elaborate. | `exact`: Asks the questions exactly as provided, without rephrasing â\x80\x94 for interviews built from your own questions (create_interview_from_questions) where the wording is a script.."}, 'interview_type': {'enum': ['pre-screening', 'pre-screening-with-test-questions', 'second-interview', 'remote-freelancer-verification', 'strength-based-interview', 'potential-based-interview', 'process-verification-from-knowledge-base', None], 'type': ['string', 'null'], 'example': 'pre-screening-with-test-questions', 'description': 'Interview style â\x80\x94 configures the AI avatar and the follow-up questions it generates during the interview. The base `questions` you supply are used as-is and are NOT affected by this setting. Options â\x80\x94 `pre-screening`: Pre-screening â\x80\x94 quick qualification check focusing on basic requirements and availability. | `pre-screening-with-test-questions`: Pre-screening with test questions â\x80\x94 pre-screening plus practical questions to test relevant skills. | `second-interview`: Second round interview â\x80\x94 deeper dive for candidates who passed initial screening. | `remote-freelancer-verification`: Remote worker verification â\x80\x94 verify remote work capabilities and communication skills. | `strength-based-interview`: Strength-based interview â\x80\x94 focus on what candidates enjoy and excel at to predict job satisfaction. | `potential-based-interview`: Potential-based interview â\x80\x94 assess learning ability and growth potential rather than past experience. | `process-verification-from-knowledge-base`: Knowledge Base interview â\x80\x94 generate questions from your knowledge base documents..'}, 'conversation_id': {'type': 'string', 'description': "Pass the exact conversation_id from the server's previous response, unchanged. The server provides it on the first call â\x80\x94 never invent one, and do not issue parallel tool calls until you have it. Keep passing the same conversation_id for the rest of the conversation, including after later user messages or on a different task; do not reset it when the user starts a new request."}, 'cover_image_url': {'type': ['string', 'null'], 'description': 'Cover image URL.'}, 'seniority_level': {'enum': ['entry-level', 'intermediate', 'senior', 'managerial', 'director', 'executive', None], 'type': ['string', 'null'], 'example': 'senior', 'description': 'Target seniority level for the role; auto-detected from the job description when omitted. Options â\x80\x94 `entry-level`: Early-career or graduate roles. | `intermediate`: Some experience required. | `senior`: Experienced professional. | `managerial`: Team or department lead. | `director`: Director-level responsibility. | `executive`: C-suite or executive role..'}, 'welcome_message': {'type': ['string', 'null'], 'description': 'Custom welcome message.'}, 'description_long': {'type': ['string', 'null'], 'description': 'Long-form interview description. Rendered as Markdown on the candidate-facing position page, including chips, callouts, cards, columns and buttons â\x80\x94 formatting guide: https://developer.jobmojito.com/cookbooks/format-content-with-markdown'}, 'interview_salary': {'type': ['string', 'null'], 'example': '$80k - $100k', 'description': 'Salary range shown for the position.'}, 'thank_you_message': {'type': ['string', 'null'], 'description': 'Custom thank-you message.'}, 'additional_context': {'type': ['object', 'null'], 'description': 'Extra context forwarded to expectation generation.', 'additionalProperties': {}}, 'hiring_for_company': {'type': ['object', 'null'], 'example': {'name': 'undisclosed'}, 'properties': {'name': {'type': ['string', 'null'], 'example': 'Unimo Enterprises', 'description': "End-employer name. Omit/null when hiring for yourself, 'undisclosed' for an unnamed external client, or the client's company name."}, 'sector': {'type': ['string', 'null'], 'example': 'Logistics and Supply Chain', 'description': 'Industry / sector of the end employer.'}, 'location': {'type': ['string', 'null'], 'example': 'Sri Lanka', 'description': 'Primary location of the end employer.'}, 'description': {'type': ['string', 'null'], 'example': 'Unimo Enterprises is a leading logistics and supply chain solutions provider.', 'description': 'Short description of the end employer, used as background context by the agent.'}, 'company_size': {'type': ['string', 'null'], 'example': '100-200', 'description': 'Approximate headcount of the end employer.'}}, 'description': "Who the position is really for. Omit/null (or an object with name null/blank) when hiring for yourself; { name: 'undisclosed' } for an unnamed external client; or { name: '<company>' } plus optional description/location/sector/company_size for a named client. Stored in creation_parameters.hiring_for_company."}, 'interview_attempts': {'type': ['number', 'null'], 'example': 1, 'description': 'Allowed attempts, 1-20.'}, 'instructional_video': {'type': ['boolean', 'null'], 'description': 'Enable an instructional video before approval.'}, 'interview_department': {'type': ['string', 'null'], 'example': 'Engineering', 'description': 'Department the position belongs to.'}, 'mojito_language_code': {'enum': ['ar', 'bg', 'zh', 'hr', 'cs', 'da', 'nl', 'en', 'fil', 'fi', 'fr', 'de', 'el', 'hi', 'hu', 'id', 'it', 'ja', 'ko', 'ms', 'no', 'pl', 'pt', 'br', 'ro', 'ru', 'sk', 'es', 'sv', 'ta', 'th', 'tr', 'uk', 'vi', None], 'type': ['string', 'null'], 'example': 'en', 'description': 'Platform language code (one of the platform-languages.json codes); must also resolve to a supported language with an Azure speech mapping.'}, 'recruiter_profile_id': {'type': ['string', 'null'], 'description': 'Profile id of the recruiter owning this interview. Must be a merchant/merchant_owner/admin profile of the same merchant.'}, 'disable_deduplication': {'type': ['boolean', 'null'], 'description': 'When true, skip step deduplication on insert.'}, 'interview_template_id': {'type': ['string', 'null'], 'example': '46b98d37-1557-4391-beca-03037ead19f2', 'minLength': 1, 'description': 'Id of the interview template to use. Must reference an existing interview_templates row.'}, 'candidate_expectations': {'type': ['string', 'null'], 'description': 'Free-text candidate expectations.'}, 'pdf_export_auto_config': {'type': ['object', 'null'], 'properties': {'files': {'type': ['boolean', 'null'], 'description': 'Include uploaded candidate files.'}, 'template': {'enum': ['classic', 'modern', 'one_pager', None], 'type': ['string', 'null'], 'description': 'Report layout: classic, modern, or one_pager. Omit for the merchant default (modern when unset).'}, 'analytics': {'type': ['boolean', 'null'], 'description': 'Include analytics.'}, 'transcript': {'type': ['boolean', 'null'], 'description': 'Include the interview transcript.'}, 'contact_details': {'type': ['boolean', 'null'], 'description': 'Include candidate contact details.'}, 'answer_recording': {'type': ['boolean', 'null'], 'description': 'Include per-answer recordings.'}, 'ai_scoring_rubric': {'type': ['boolean', 'null'], 'description': 'Include the AI scoring rubric.'}, 'group_by_question': {'type': ['boolean', 'null'], 'description': 'Group transcript answers by expected question.'}, 'session_recording': {'type': ['boolean', 'null'], 'description': 'Include the full-session recording.'}, 'mojito_language_code': {'enum': ['ar', 'bg', 'zh', 'hr', 'cs', 'da', 'nl', 'en', 'fil', 'fi', 'fr', 'de', 'el', 'hi', 'hu', 'id', 'it', 'ja', 'ko', 'ms', 'no', 'pl', 'pt', 'br', 'ro', 'ru', 'sk', 'es', 'sv', 'ta', 'th', 'tr', 'uk', 'vi', None], 'type': ['string', 'null'], 'example': 'en', 'description': 'Report language code (a platform-languages.json code).'}, 'ai_recruiter_assessment': {'type': ['boolean', 'null'], 'description': 'Include the AI recruiter assessment.'}}, 'description': 'Auto-generate a candidate PDF report with these options once the interview completes. null disables auto-export.'}, 'recording_full_session': {'enum': ['audio_all', 'video_all', None], 'type': ['string', 'null'], 'example': 'video_all', 'description': 'Full interview-session recording (includes the avatar and voice) produced as a single file. Independent of `recording`. Omit/null to disable. Options â\x80\x94 `audio_all`: Record the whole session audio (avatar + candidate voice) into a single file. Adds +0.2 credits. | `video_all`: Record the whole session video + audio (avatar + candidate) into a single file. Adds +0.4 credits..'}, 'required_pronunciation': {'type': ['boolean', 'null'], 'example': False, 'description': 'Require pronunciation assessment (restricts to pronunciation-capable languages). Defaults to false.'}, 'knowledge_base_store_id': {'type': ['string', 'null'], 'description': 'Optional knowledge base store id; validated for existence.'}, 'questions_random_subset': {'type': ['number', 'null'], 'description': 'Fraction of questions to randomly ask, between 0.01 and 0.9.'}, 'interview_available_till': {'type': ['string', 'null'], 'example': '2026-12-31', 'description': 'ISO date/time after which the interview is no longer available to candidates. null keeps it always available.'}, 'candidate_expectations_json': {'type': ['object', 'null'], 'properties': {'weak': {'type': ['array', 'null'], 'items': {'type': 'string'}, 'description': 'Baseline requirements every viable candidate should meet (table stakes).'}, 'strong': {'type': ['array', 'null'], 'items': {'type': 'string'}, 'description': 'High-bar requirements only standout candidates clear.'}, 'moderate': {'type': ['array', 'null'], 'items': {'type': 'string'}, 'description': 'Requirements expected of a solid, competent candidate.'}}, 'description': 'Pre-generated candidate expectations, bucketed by requirement level (weak/moderate/strong); auto-generated when omitted for type=interview. Extra keys are preserved.'}, 'candidate_video_introduction': {'enum': ['optional', 'required', None], 'type': ['string', 'null'], 'description': 'Whether a candidate video introduction is optional or required.'}, 'interview_conversation_speed': {'enum': ['slower', 'normal', 'faster', None], 'type': ['string', 'null'], 'example': 'normal', 'description': 'Conversation pace of the AI avatar. Omit/null keeps the template default pace. Options â\x80\x94 `slower`: The avatar speaks more slowly â\x80\x94 easier to follow for non-native speakers. | `normal`: Default speaking pace. | `faster`: The avatar speaks more quickly for a snappier conversation..'}, 'result_enable_edit_transcript': {'type': ['boolean', 'null'], 'example': True, 'description': 'Allow editing the transcript on the result view. Defaults to true.'}, 'instructional_video_custom_text': {'type': ['string', 'null'], 'description': 'Custom text for the instructional video.'}}}
输出模式
{'type': 'object', 'required': ['interview_def_set_id'], 'properties': {'embed_id': {'type': ['string', 'null'], 'description': 'Embed id, present only when is_embedded=true.'}, '_mcp_instructions': {'type': 'object', 'properties': {'conversation_id': {'type': 'string', 'description': 'The server-issued conversation identifier.'}}, 'description': 'Server-issued metadata for this conversation.'}, 'embed_signing_key': {'type': ['string', 'null'], 'description': 'Embed signing key, present only when is_embedded=true.'}, 'interview_def_set_id': {'type': ['string', 'null'], 'description': 'Id of the newly created interview definition set.'}}, 'description': 'The created interview definition set id, plus embed credentials when is_embedded=true.', 'x-fastmcp-top-level-schema': 'JobInterviewCreateFromArrayResponse'}
create_persona
Create role-play persona
[Interviews] Create a role-play persona: an avatar that plays a defined role in a free-form conversation instead of a scored Q&A interview. FIRST CHOOSE `portal`, because it selects between two different products: `portal="interview"` builds a SIMULATED PERSONA a recruiter invites candidates to — scored, billed to merchant credits, and listed with the recruiter's other results; `portal="coaching"` (THE DEFAULT) builds a coaching persona learners start themselves from the catalogue, billed to their own coaching credits and never visible to recruiters. Pass `portal="interview"` explicitly for any hiring, screening or assessment use. Then set `persona_role_avatar`/`persona_role_user` for the roles and `opening_line` for the avatar's first spoken line (defaults to a generic 'Hello'). FIRST DECIDE `portal`. This endpoint creates two different products and the default is NOT the recruiter one: - `portal: "interview"` — an INTERVIEW ROLE-PLAY. Use this whenever the goal is to ASSESS or SCREEN candidates: hiring, assessments, sales role-plays for job applicants, anything a recruiter runs. Candidates are invited through the normal invitation flow, results appear in the recruiter's result list, it is billed against merchant credits, and attempts are capped via `interview_attempts` — exactly like an interview. - `portal: "coaching"` (THE DEFAULT) — a coaching persona for practice/training on the coaching portal. Consumed against the mentee's own coaching credits, self-started from the catalogue, and its results are NOT visible to recruiters. Omitting `portal` gives you this one, so pass `portal: "interview"` explicitly for any recruiting/assessment use case. The conversation itself behaves identically in both. The avatar plays a defined role in a free-form conversation instead of running a scored Q&A interview. No AI question/description generation runs; the persona role fields ARE the configuration. The session runs as: a welcome message → the avatar's OPENING LINE (the first thing it says, set via `opening_line`) → the candidate replies and the free-form role-play begins → a closing message. Because there is no question list, `opening_line` is how the avatar starts the scene — set it to a concrete in-character line; if omitted it defaults to a generic "Hello". Set `welcome_message` and `thank_you_message` too — omitting them leaves the generic platform defaults. Also set `candidate_expectations`: it is the yardstick the session is scored against. The four avatar prompts divide up as: `persona_avatar_who_is` (identity and what drives it), `persona_avatar_knowledge` (the private facts it may use), `persona_avatar_progress` (how the conversation is allowed to move forward, and what gates the later personal details), and `persona_avatar_end_conditions` (when to stop). Without `persona_avatar_progress` the avatar has no defined arc and tends to either concede immediately or never concede at all. Provisions the default conversational steps and optionally an embed key.
可能执行破坏性操作 可访问外部资源
输入模式
{'type': 'object', 'required': ['name', 'interview_template_id', 'mojito_language_code', 'status', 'visibility', 'persona_role_avatar', 'persona_role_user'], 'properties': {'code': {'type': ['string', 'null'], 'example': 'my code', 'description': 'Optional external code/reference for the persona.'}, 'name': {'type': ['string', 'null'], 'example': 'Difficult customer role-play', 'minLength': 1, 'description': 'Persona / session name.'}, 'tags': {'type': ['array', 'null'], 'items': {'type': 'string'}, 'example': ['interview-practice', 'sales'], 'description': "Free-form tags stored on the persona. Tags are also the coaching-catalogue mapping key: a catalogue directory (see the catalogue-tag-create / catalogue-tag-update endpoints) lists a coaching or persona session when the session's tags contain EVERY tag in that directory's `tags_interview_set_filter`. Only `active` sessions with visibility `public` or `merchant_public` are listed."}, 'portal': {'enum': ['coaching', 'interview', None], 'type': ['string', 'null'], 'example': 'interview', 'description': "REQUIRED IN PRACTICE â\x80\x94 pick deliberately; the default is the coaching product, not the recruiting one. `interview`: an interview role-play. Choose this for ANY recruiting or assessment use case (screening candidates, hiring, sales role-plays for applicants). Candidates are invited through the normal invitation flow, results are visible to the recruiter alongside ordinary interview results, it is billed against your merchant credits on the same basis as an interview, and attempts are capped (see `interview_attempts`). | `coaching` (DEFAULT when omitted): the classic coaching persona for practice/training. Runs on the coaching portal, is consumed against the mentee's own coaching credits, is started by the mentee from the catalogue or a shared link, and its results are NOT visible to recruiters. The conversation itself behaves identically in both cases â\x80\x94 only the portal, billing, visibility and attempt limits differ."}, 'status': {'enum': ['draft', 'active', None], 'type': ['string', 'null'], 'example': 'active', 'description': 'Lifecycle status of the interview. Options â\x80\x94 `draft`: Created but not published â\x80\x94 not visible to candidates and cannot be run yet. Use to stage an interview before going live. | `active`: Published and live â\x80\x94 candidates can run it..'}, 'recording': {'enum': ['audio_first_5_answers', 'audio_all', 'video_all', 'video_first_5_answers', None], 'type': ['string', 'null'], 'example': 'video_all', 'description': 'Cheating/proctoring detection mode for candidate answers â\x80\x94 this is NOT a full session recording. Video options also record the candidate. Omit/null to disable. Options â\x80\x94 `audio_first_5_answers`: Audio-only cheating detection, first 5 answers only. | `audio_all`: Audio-only cheating detection on every answer. | `video_all`: Audio + video cheating detection on every answer (candidate is recorded for all answers). | `video_first_5_answers`: Audio + video cheating detection, first 5 answers only..'}, 'visibility': {'enum': ['merchant_public', 'merchant_invite', 'merchant_unlisted', None], 'type': ['string', 'null'], 'example': 'merchant_public', 'description': "Who can discover and access the interview. Options â\x80\x94 `merchant_public`: Listed on the merchant's public interview list â\x80\x94 anyone with the merchant link can find and start it. | `merchant_invite`: Invite-only â\x80\x94 only candidates explicitly invited (by email/link) can access it; not listed anywhere. | `merchant_unlisted`: Reachable only via a direct link â\x80\x94 not listed anywhere; share the link manually.."}, 'description': {'type': ['string', 'null'], 'example': 'A quick sales role-play with an unhappy customer. Your goal is to resolve their complaint and keep the account.', 'description': 'Short persona description shown to the candidate on the pre-session poster. Candidate-visible â\x80\x94 keep it to max 2 sentences. Unlike job-interview-create, personas run no AI generation, so this is never auto-generated: leave it null/blank and the poster simply shows no description; set it to frame the scene.'}, 'environment': {'enum': ['production', 'uat', 'development', 'demo', None], 'type': ['string', 'null'], 'example': 'production', 'description': 'Which of your webhook environments results from this interview are delivered to. Defaults to production. Options â\x80\x94 `production`: Live hiring. Results reach the webhooks configured as production. This is the default when the field is omitted. | `uat`: User-acceptance testing - an isolated environment for pre-release verification. | `development`: Development/testing. Use for interviews created by a test or preview app so their results never reach the production webhook. | `demo`: Demonstrations and sales trials..'}, 'is_embedded': {'type': ['boolean', 'null'], 'example': False, 'description': 'Set true when the persona will be embedded as an iframe on an external page. Provisions an embed key and returns embed_id / embed_signing_key.'}, 'merchant_id': {'type': ['string', 'null'], 'example': '28106cba-1c27-4e53-b149-32113e5e8e31', 'description': 'Merchant id. Admin / sub-merchant callers only; otherwise taken from your token.'}, 'result_view': {'enum': ['none', 'minimal', 'minimal_with_score', 'advanced', 'full', 'full_expand_scores', None], 'type': ['string', 'null'], 'example': 'full', 'description': 'Result screen shown to the candidate after finishing. With any value other than `none`, the candidate sees a results screen where they can provide feedback, record an intro video and edit the transcript, and must then submit the result; the value sets how much score/result detail is shown. Options â\x80\x94 `none`: No results screen at all â\x80\x94 the interview is submitted immediately when the candidate finishes (no feedback, intro video, transcript edit or manual submit step). | `minimal`: Minimal results layout, no score shown. | `minimal_with_score`: Minimal results layout including the overall score. | `advanced`: Advanced results layout with more detail. | `full`: Full results layout with all sections. | `full_expand_scores`: Full results with every score breakdown expanded..'}, 'max_duration': {'type': ['number', 'null'], 'example': 1200, 'description': 'Maximum conversation duration in seconds. Defaults to 1200 (20 min) when omitted.'}, 'opening_line': {'type': ['string', 'null'], 'example': "Oh, finally â\x80\x94 someone actually comes over! I've been waiting for ages. Are you going to help me or not?", 'description': 'The avatar\'s opening line â\x80\x94 the FIRST thing it says out loud when the session starts, before the candidate has said anything. This is a literal spoken line, NOT a description: write the exact words the avatar should say, in character and consistent with persona_role_avatar. For an escalated scenario it should already convey that state (e.g. an angry customer opens angrily). If omitted, the platform inserts a generic default ("Hello"), which is usually a weak opener â\x80\x94 set this for anything other than a neutral greeting.'}, 'conversation_id': {'type': 'string', 'description': "Pass the exact conversation_id from the server's previous response, unchanged. The server provides it on the first call â\x80\x94 never invent one, and do not issue parallel tool calls until you have it. Keep passing the same conversation_id for the rest of the conversation, including after later user messages or on a different task; do not reset it when the user starts a new request."}, 'cover_image_url': {'type': ['string', 'null'], 'example': 'https://example.com/cover.png', 'description': 'Cover image URL.'}, 'welcome_message': {'type': ['string', 'null'], 'example': 'Welcome! You are about to speak with a customer who is unhappy about a recent price increase.', 'description': "Custom welcome message spoken to the candidate before the role-play starts â\x80\x94 set it; omitting it leaves a generic platform default. This is the scene-setting message; the avatar's first in-character line is `opening_line`, which comes after it."}, 'persona_role_user': {'type': ['string', 'null'], 'example': 'is to be a sales person trying to sell an additional product to the customer', 'minLength': 1, 'description': "The role the candidate (mentee) plays. Candidate-visible â\x80\x94 shown on the pre-session poster as 'Your role', so write it as candidate-facing setup and keep it to max 2 sentences. Example: 'is to be a sales person trying to sell an additional product to the customer'."}, 'thank_you_message': {'type': ['string', 'null'], 'example': 'Thanks â\x80\x94 your role-play has been recorded and will be reviewed by the hiring team.', 'description': 'Custom thank-you message shown after the session â\x80\x94 set it; omitting it leaves a generic platform default.'}, 'interview_attempts': {'type': ['number', 'null'], 'example': 3, 'maximum': 20.0, 'minimum': 1.0, 'description': 'Allowed candidate attempts (1-20), defaulting to 3. Only meaningful when `portal` is `interview`; coaching personas are unlimited. A recruiter can still grant an extra attempt afterwards.'}, 'interview_location': {'type': ['string', 'null'], 'example': 'remote', 'description': 'Optional location label shown for the session.'}, 'persona_role_avatar': {'type': ['string', 'null'], 'example': 'is to act as a happy customer responding to questions', 'minLength': 1, 'description': "The role the AI avatar plays. Candidate-visible â\x80\x94 shown on the pre-session poster as 'Role of the agent', so write it as candidate-facing setup and keep it to max 2 sentences. Example: 'is to act as a happy customer responding to questions'."}, 'mojito_language_code': {'enum': ['ar', 'bg', 'zh', 'hr', 'cs', 'da', 'nl', 'en', 'fil', 'fi', 'fr', 'de', 'el', 'hi', 'hu', 'id', 'it', 'ja', 'ko', 'ms', 'no', 'pl', 'pt', 'br', 'ro', 'ru', 'sk', 'es', 'sv', 'ta', 'th', 'tr', 'uk', 'vi', None], 'type': ['string', 'null'], 'example': 'en', 'description': 'Platform language code used for the conversation. Must be one of the platform-languages.json codes.'}, 'recruiter_profile_id': {'type': ['string', 'null'], 'description': 'Profile id of the recruiter owning this persona. Must be a merchant/merchant_owner/admin profile of the same merchant.'}, 'interview_template_id': {'type': ['string', 'null'], 'format': 'uuid', 'example': 'baa3bf7c-6926-46fd-9005-16738a31f72d', 'minLength': 1, 'description': 'Id of the interview template (avatar) the persona uses.'}, 'persona_avatar_who_is': {'type': ['string', 'null'], 'description': 'Who the avatar represents: name, role, context, personality, woven with what drives them underneath (motive, fear, what they refuse until heard, what they do not know until told). One continuous description; no labelled subsections.'}, 'candidate_expectations': {'type': ['string', 'null'], 'maxLength': 2100, 'description': 'Mentee assessment goals â\x80\x94 free-text describing what the candidate is expected to achieve (max 2100 chars).'}, 'recording_full_session': {'enum': ['audio_all', 'video_all', None], 'type': ['string', 'null'], 'example': 'video_all', 'description': 'Full interview-session recording (includes the avatar and voice) produced as a single file. Independent of `recording`. Omit/null to disable. Options â\x80\x94 `audio_all`: Record the whole session audio (avatar + candidate voice) into a single file. Adds +0.2 credits. | `video_all`: Record the whole session video + audio (avatar + candidate) into a single file. Adds +0.4 credits..'}, 'persona_avatar_progress': {'type': ['string', 'null'], 'example': 'Mode: turning point\nInitial hold: ...\nUnlocks when: ...\nAfter unlock: ...\nHard limits: ...\nNo goalposts: ...\nGates: ...', 'description': 'How the conversation moves forward â\x80\x94 one plain-text value starting with `Mode: turning point` (resistance) or `Mode: steps` (difficult conversation protocol), then the labelled lines for that mode (Initial hold / Unlocks when / â\x80¦ or Framework / Steps / â\x80¦), including a Gates line: do not share later personal details from persona_avatar_knowledge until progress is earned.'}, 'persona_avatar_knowledge': {'type': ['string', 'null'], 'description': 'Private facts the avatar can use (numbers, dates, names, objections), plus any personal details shareable only after progress and only if natural â\x80\x94 timing written inline, not as labelled subsections. Those personal details are never required for the goal.'}, 'candidate_video_introduction': {'enum': ['optional', 'required', None], 'type': ['string', 'null'], 'example': 'optional', 'description': 'Whether a candidate video introduction is optional or required.'}, 'interview_conversation_speed': {'enum': ['slower', 'normal', 'faster', None], 'type': ['string', 'null'], 'example': 'normal', 'description': 'Conversation pace of the AI avatar. Omit/null keeps the template default pace. Options â\x80\x94 `slower`: The avatar speaks more slowly â\x80\x94 easier to follow for non-native speakers. | `normal`: Default speaking pace. | `faster`: The avatar speaks more quickly for a snappier conversation..'}, 'persona_avatar_end_conditions': {'type': ['string', 'null'], 'description': 'When the avatar should end the session. Prefer referring to persona_avatar_progress: wrap up when progress is complete (turning point unlocked and a plan accepted, or steps "Done when" reached), or when the conversation has clearly broken down.'}}}
输出模式
{'type': 'object', 'required': ['interview_def_set_id'], 'properties': {'embed_id': {'type': ['string', 'null'], 'description': 'Embed id, present only when is_embedded=true.'}, '_mcp_instructions': {'type': 'object', 'properties': {'conversation_id': {'type': 'string', 'description': 'The server-issued conversation identifier.'}}, 'description': 'Server-issued metadata for this conversation.'}, 'embed_signing_key': {'type': ['string', 'null'], 'description': 'Embed signing key, present only when is_embedded=true.'}, 'interview_def_set_id': {'type': ['string', 'null'], 'example': '00000000-0000-0000-0000-000000000000', 'description': 'Id of the newly created persona definition set.'}}, 'description': 'Id of the created persona. Includes embed_id/embed_signing_key when is_embedded=true.', 'x-fastmcp-top-level-schema': 'PersonaCreateResponse'}
generate_interview_report
Generate interview report
[Results] Generate an interview result report (HTML/PDF/JSON) for a completed interview. The report is decision-support material for a human reviewer, not an automated hiring decision. Generates an interview result report as a PDF (returns a signed URL), raw HTML, or structured JSON. Provide either `interview_result_id` for a single result or `interview_result_ids` for a combined multi-result report.
可能执行破坏性操作 可访问外部资源 幂等
输入模式
{'type': 'object', 'required': ['export_type'], 'properties': {'template': {'allOf': [{'enum': ['classic', 'modern', 'one_pager'], 'type': 'string', 'example': 'modern', 'description': 'Report layout for this export. Same values as the top-level `template`; the top-level field wins when both are given. Kept here so a saved auto-export configuration carries its template.'}, {'description': 'Report layout: `classic`, `modern` or `one_pager`. Omit for the merchant default (modern when unset).'}]}, 'store_file': {'type': ['boolean', 'null'], 'description': 'When true (pdf only), persist the file to storage and return a signed URL.'}, 'export_type': {'enum': ['pdf', 'html', 'json', None], 'type': ['string', 'null']}, 'conversation_id': {'type': 'string', 'description': "Pass the exact conversation_id from the server's previous response, unchanged. The server provides it on the first call â\x80\x94 never invent one, and do not issue parallel tool calls until you have it. Keep passing the same conversation_id for the rest of the conversation, including after later user messages or on a different task; do not reset it when the user starts a new request."}, 'interview_result_id': {'type': ['string', 'null'], 'format': 'uuid', 'example': '93c98d21-e04d-4a84-9afa-ed154cf73636'}, 'interview_result_ids': {'type': ['array', 'null'], 'items': {'type': 'string', 'format': 'uuid'}, 'description': 'Generate a single combined report for multiple results.'}, 'export_features_result': {'type': 'object', 'properties': {'files': {'type': ['boolean', 'null'], 'default': True, 'description': "Include the candidate's uploaded files (resume and cover letter) as signed page URLs."}, 'template': {'enum': ['classic', 'modern', 'one_pager'], 'type': 'string', 'example': 'modern', 'description': 'Report layout for this export. Same values as the top-level `template`; the top-level field wins when both are given. Kept here so a saved auto-export configuration carries its template.'}, 'analytics': {'type': ['boolean', 'null'], 'default': True, 'description': 'Include speech analytics for each answer (speech accuracy, fluency, recognition confidence, sentiment, cadence / words-per-minute).'}, 'transcript': {'type': ['boolean', 'null'], 'default': True, 'description': 'Include the full interview transcript: each question, the candidate answer, and the per-answer AI analysis.'}, 'contact_details': {'type': ['boolean', 'null'], 'default': True, 'description': "Include the candidate's contact details (email, LinkedIn, phone number, physical address)."}, 'answer_recording': {'type': ['boolean', 'null'], 'default': False, 'description': 'Include a signed recording URL (audio/video) for each individual answer.'}, 'ai_scoring_rubric': {'type': ['boolean', 'null'], 'default': False, 'description': 'Include the AI scoring rubric â\x80\x94 the candidate-expectation buckets (strong / moderate / weak). Only takes effect when ai_recruiter_assessment is also true.'}, 'group_by_question': {'type': ['boolean', 'null'], 'default': False, 'description': 'Group answers under their expected questions (instead of chronological order), including questions that were not reached.'}, 'session_recording': {'type': ['boolean', 'null'], 'default': False, 'description': 'Include the full interview session recording and the video introduction as signed URLs.'}, 'mojito_language_code': {'enum': ['ar', 'bg', 'zh', 'hr', 'cs', 'da', 'nl', 'en', 'fil', 'fi', 'fr', 'de', 'el', 'hi', 'hu', 'id', 'it', 'ja', 'ko', 'ms', 'no', 'pl', 'pt', 'br', 'ro', 'ru', 'sk', 'es', 'sv', 'ta', 'th', 'tr', 'uk', 'vi', None], 'type': ['string', 'null'], 'example': 'en', 'description': "Report language. Optional: if omitted, the report uses each result's own language code. If provided and it differs from the result's language, the report content is translated, which costs 0.1 credit per result."}, 'ai_recruiter_assessment': {'type': ['boolean', 'null'], 'default': True, 'description': 'Include the AI recruiter assessment: resume analysis, overall AI analysis, and the why-hire / why-not-hire summaries.'}}}}}
输出模式
{'type': 'object', 'required': ['result'], 'properties': {'result': {'anyOf': [{'type': 'object', 'title': 'PDF export', 'required': ['pdf_export_url', 'pdf_export_valid_until'], 'properties': {'pdf_export_url': {'type': ['string', 'null'], 'format': 'uri', 'description': 'Signed URL of the generated PDF.'}, 'pdf_export_valid_until': {'type': ['string', 'null'], 'example': '2026-09-01T12:00:00.000Z', 'description': 'ISO timestamp until which the signed URL is valid.'}}, 'description': 'Returned when `export_type` is `pdf`.'}, {'type': 'object', 'title': 'HTML export', 'required': ['html_export'], 'properties': {'html_export': {'type': ['string', 'null'], 'description': 'The full report rendered as an HTML document string.'}}, 'description': 'Returned when `export_type` is `html`.'}, {'type': 'object', 'title': 'JSON export', 'required': ['json_export'], 'properties': {'json_export': {'type': ['object', 'null'], 'required': ['results'], 'properties': {'table': {'type': ['string', 'null'], 'description': 'Overview table HTML, present only for multi-result exports.'}, 'results': {'type': ['array', 'null'], 'items': {'type': 'object', 'required': ['data', 'files'], 'properties': {'data': {'type': ['object', 'null'], 'additionalProperties': {}}, 'files': {'type': ['array', 'null'], 'items': {'type': 'object', 'required': ['type', 'page', 'page_signed'], 'properties': {'page': {'type': ['number', 'null']}, 'type': {'type': ['string', 'null']}, 'page_signed': {'type': ['string', 'null']}}}}}}}}}}, 'description': 'Returned when `export_type` is `json`.'}], 'description': 'The generated report. Exactly one of the three shapes below is returned, selected by the request `export_type`: `pdf` â\x86\x92 `{ pdf_export_url, pdf_export_valid_until }`; `html` â\x86\x92 `{ html_export }`; `json` â\x86\x92 `{ json_export }`.', 'x-fastmcp-top-level-schema': 'JobInterviewPdfResponse'}, '_mcp_instructions': {'type': 'object', 'properties': {'conversation_id': {'type': 'string', 'description': 'The server-issued conversation identifier.'}}, 'description': 'Server-issued metadata for this conversation.'}}, 'x-fastmcp-wrap-result': True}
generate_interview_url
Generate shareable interview link
[Interviews] Generate a signed public interview URL/token. Generates a public, token-signed URL for an existing interview, profile, or result. The required id fields depend on `type`.
可能执行破坏性操作 可访问外部资源
输入模式
{'type': 'object', 'required': ['type'], 'properties': {'type': {'enum': ['interview-for-profile', 'results-for-profile', 'interview-result-candidate', 'interview-result-talent-seeker', 'interview-results-for-position', None], 'type': ['string', 'null'], 'description': 'Which kind of signed URL to generate.'}, 'hide_menu': {'anyOf': [{'type': 'string'}, {'type': 'boolean'}], 'description': "Pass the string 'false' to show the navigation menu; any other value hides it (default)."}, 'merchant_id': {'type': ['string', 'null'], 'description': 'Override merchant id (admin / sub-merchant only).'}, 'interview_id': {'type': ['string', 'null'], 'description': 'Interview or position id. Required for interview-for-profile and interview-results-for-position.'}, 'conversation_id': {'type': 'string', 'description': "Pass the exact conversation_id from the server's previous response, unchanged. The server provides it on the first call â\x80\x94 never invent one, and do not issue parallel tool calls until you have it. Keep passing the same conversation_id for the rest of the conversation, including after later user messages or on a different task; do not reset it when the user starts a new request."}, 'interview_result_id': {'type': ['string', 'null'], 'description': 'Interview result id. Required for interview-result-candidate and interview-result-talent-seeker.'}, 'interview_profile_id': {'type': ['string', 'null'], 'description': 'Candidate profile id. Required for interview-for-profile and results-for-profile.'}}}
输出模式
{'type': 'object', 'required': ['result'], 'properties': {'result': {'type': 'string', 'example': 'https://interviews.example.com/interview/take/<id>/?interview_token=<jwt>&view_hm=true', 'description': 'The signed interview URL.', 'x-fastmcp-top-level-schema': 'JobInterviewTokenResponse'}, '_mcp_instructions': {'type': 'object', 'properties': {'conversation_id': {'type': 'string', 'description': 'The server-issued conversation identifier.'}}, 'description': 'Server-issued metadata for this conversation.'}}, 'x-fastmcp-wrap-result': True}
get_catalogue_directory
Get coaching catalogue directory
[Coaching catalogue] Read one catalogue directory in full: its settings, its custom Markdown page (`content_md`), its resolved sub-directories, and the coaching sessions its tag filter currently matches — which is how you verify that a session's `tags` actually place it in this directory. Read before updating: `content_md`, `tags_sub` and `tags_interview_set_filter` are replaced wholesale, so you need the current value to extend it. Reads one catalogue directory in full: its settings, its custom Markdown page (`content_md`), the sub-directories it nests, and the coaching sessions its `tags_interview_set_filter` currently matches. Read a directory before updating it — `content_md`, `tags_sub` and `tags_interview_set_filter` are replaced wholesale by catalogue-tag-update, so you need the current value to extend rather than overwrite it.
只读 可访问外部资源 幂等
输入模式
{'type': 'object', 'required': ['id'], 'properties': {'id': {'type': 'string', 'example': 'sales-coaching-en', 'minLength': 1, 'description': 'Id of the catalogue directory to read (the catalogue URL segment).'}, 'merchant_id': {'type': 'string', 'format': 'uuid', 'example': '28106cba-1c27-4e53-b149-32113e5e8e31', 'description': "Optional merchant to scope to. Admins and sub-merchant operators only; other callers always use their token's merchant."}, 'conversation_id': {'type': 'string', 'description': "Pass the exact conversation_id from the server's previous response, unchanged. The server provides it on the first call â\x80\x94 never invent one, and do not issue parallel tool calls until you have it. Keep passing the same conversation_id for the rest of the conversation, including after later user messages or on a different task; do not reset it when the user starts a new request."}}}
输出模式
{'type': 'object', 'required': ['id', 'name', 'description', 'mojito_language_code', 'visibility', 'status', 'coach_plan', 'cover_image_url', 'merchant_id', 'tags_sub', 'tags_interview_set_filter', 'content_md', 'created_at', 'updated_at', 'catalogue_url', 'is_start_directory', 'sub_directories', 'matched_sessions', 'matched_sessions_truncated'], 'properties': {'id': {'type': ['string', 'null'], 'example': 'sales-coaching-en', 'description': 'Directory id â\x80\x94 also the catalogue URL segment.'}, 'name': {'type': ['string', 'null'], 'description': 'Display name.'}, 'status': {'type': ['string', 'null'], 'description': 'Lifecycle status.'}, 'tags_sub': {'type': ['array', 'null'], 'items': {'type': 'string'}, 'example': ['sales-coaching-objections-en', 'sales-coaching-closing-en'], 'description': 'Ids of the directories nested under this one, in display order. Replaces the whole list â\x80\x94 send the full set, not just the additions. A referenced directory only appears if it exists and is visible to the viewer.'}, 'coach_plan': {'type': ['string', 'null'], 'description': 'Coaching-plan stage, when the directory belongs to one.'}, 'content_md': {'type': ['string', 'null'], 'example': '## Sales coaching\n\nPick a session to practise with.\n\n[chip:6 sessions] [chip:Beginner,tone=accent]\n\n[sessions:filter=objection-handling,limit=6]\n', 'description': "Markdown for a custom directory page. When set (even as an empty string) the markdown replaces the default grid and decides the layout itself; null renders the plain grid of sub-directories and sessions. Alongside normal Markdown you can place these directives, each ALONE on its own line: `[plan-progress]` (the learner's coaching-plan progress), `[directory:<tag-id>]` (a card for one sub-directory), `[session:<interview-id>]` (a card for one session), `[sessions]` (every session in this directory), `[sessions:<term>]` (sessions matching a term), `[sessions:filter=<term>,limit=<n>]` (a filtered, capped list). A directive on a line with other text is rendered as ordinary text. Chips, callouts, cards, columns and buttons are available here too â\x80\x94 full vocabulary: https://developer.jobmojito.com/cookbooks/format-content-with-markdown"}, 'created_at': {'type': ['string', 'null'], 'description': 'Creation timestamp (ISO 8601).'}, 'updated_at': {'type': ['string', 'null'], 'description': 'Last update timestamp (ISO 8601).'}, 'visibility': {'type': ['string', 'null'], 'description': 'Who can see it.'}, 'description': {'type': ['string', 'null'], 'description': 'Short description shown on the directory card.'}, 'merchant_id': {'type': ['string', 'null'], 'description': 'Owning merchant id. Null for a platform-wide directory.'}, 'catalogue_url': {'type': ['string', 'null'], 'example': 'https://coaching.example.com/catalogue/sales-coaching-en', 'description': 'Public URL of this directory page, when the merchant has a coaching-portal domain configured.'}, 'cover_image_url': {'type': ['string', 'null'], 'description': 'Cover image URL.'}, 'sub_directories': {'type': ['array', 'null'], 'items': {'type': 'object', 'required': ['id', 'name', 'description', 'status', 'visibility', 'mojito_language_code'], 'properties': {'id': {'type': ['string', 'null'], 'description': 'Sub-directory id.'}, 'name': {'type': ['string', 'null'], 'description': 'Display name.'}, 'status': {'type': ['string', 'null'], 'description': 'Lifecycle status.'}, 'visibility': {'type': ['string', 'null'], 'description': 'Visibility.'}, 'description': {'type': ['string', 'null'], 'description': 'Short description.'}, 'mojito_language_code': {'type': ['string', 'null'], 'description': 'Directory language.'}}, 'additionalProperties': {}}, 'description': 'The directories listed in `tags_sub`, resolved and in display order. An id in `tags_sub` that does not resolve (deleted, or not visible to you) is simply absent here â\x80\x94 compare the two to spot a broken link.'}, 'matched_sessions': {'type': ['array', 'null'], 'items': {'type': 'object', 'required': ['id', 'name', 'type', 'type_avatar', 'status', 'visibility', 'type_credit', 'tags'], 'properties': {'id': {'type': ['string', 'null'], 'description': 'Interview definition id of the coaching/persona session.'}, 'name': {'type': ['string', 'null'], 'description': 'Session name.'}, 'tags': {'type': ['array', 'null'], 'items': {'type': 'string'}, 'description': "The session's own tags â\x80\x94 the superset that matched this directory's filter."}, 'type': {'type': ['string', 'null'], 'description': 'Product type â\x80\x94 `coaching` or `persona`.'}, 'status': {'type': ['string', 'null'], 'description': 'Lifecycle status (always `active` here â\x80\x94 nothing else is listed).'}, 'visibility': {'type': ['string', 'null'], 'description': 'Visibility.'}, 'type_avatar': {'type': ['string', 'null'], 'description': 'Avatar/voice modality of the session.'}, 'type_credit': {'type': ['string', 'null'], 'description': 'Credit bucket the session draws from.'}}, 'additionalProperties': {}}, 'description': 'The coaching/persona sessions this directory currently lists, applying the same rules as the live portal: `active`, type `coaching` or `persona`, visibility `public` or `merchant_public` for this merchant, and `tags` containing every tag of `tags_interview_set_filter`. Empty when the filter is null. Capped at 200.'}, '_mcp_instructions': {'type': 'object', 'properties': {'conversation_id': {'type': 'string', 'description': 'The server-issued conversation identifier.'}}, 'description': 'Server-issued metadata for this conversation.'}, 'is_start_directory': {'type': ['boolean', 'null'], 'description': "True when this is the directory the merchant's catalogue opens on."}, 'mojito_language_code': {'type': ['string', 'null'], 'example': 'en', 'description': 'Directory language.'}, 'tags_interview_set_filter': {'type': ['array', 'null'], 'items': {'type': 'string'}, 'example': ['sales', 'objection-handling'], 'description': 'Tag filter selecting which coaching sessions this directory lists: a session appears when its own `tags` contain EVERY tag here (an AND, not an OR). Only `active` coaching/persona sessions with visibility `public` or `merchant_public` are listed. Set the matching tags on the session with the create-interview / job-interview-update `tags` field.'}, 'matched_sessions_truncated': {'type': ['boolean', 'null'], 'description': 'True when more sessions match than the 200 returned â\x80\x94 narrow `tags_interview_set_filter` if you see this.'}}, 'description': 'One catalogue directory with its content page, sub-directories and matched sessions.', 'x-fastmcp-top-level-schema': 'CatalogueTagGetResponse'}
get_documentation
Read a JobMojito documentation page
Fetch the full content of a single JobMojito documentation page. Accepts a URL returned by `search_documentation`. For developer docs the clean Markdown (.md) variant is fetched automatically. Only developer.jobmojito.com and help.jobmojito.com URLs are allowed.
只读 可访问外部资源 幂等
输入模式
{'type': 'object', 'required': ['url'], 'properties': {'url': {'type': 'string', 'description': 'The documentation page URL.'}, 'max_chars': {'type': 'integer', 'default': 20000, 'description': 'Truncate content to this many characters (default 20000).'}, 'conversation_id': {'type': 'string', 'description': "Pass the exact conversation_id from the server's previous response, unchanged. The server provides it on the first call â\x80\x94 never invent one, and do not issue parallel tool calls until you have it. Keep passing the same conversation_id for the rest of the conversation, including after later user messages or on a different task; do not reset it when the user starts a new request."}}, 'additionalProperties': False}
输出模式
{'type': 'object', 'properties': {'_mcp_instructions': {'type': 'object', 'properties': {'conversation_id': {'type': 'string', 'description': 'The server-issued conversation identifier.'}}, 'description': 'Server-issued metadata for this conversation.'}}, 'additionalProperties': True}
get_interview_definition
Get interview definition
[Interviews] Get the definition/configuration of an interview (position), including its ordered `questions` array. The questions come back in the same format create_interview_from_questions accepts, so you can read an interview here, change the array, and send it to update_interview. Each question's `id` identifies it — keep the ids you did not mean to change. Retrieves the interview definition for a given interview-definition id or position id. Returns the compiled `calc_definition_json`, the ordered `questions` array (in the same format job-interview-create-from-array accepts, so it round-trips into job-interview-update) plus basic metadata. Access is subject to the caller's row-level security.
只读 可访问外部资源 幂等
输入模式
{'type': 'object', 'required': ['position_id'], 'properties': {'position_id': {'type': 'string', 'format': 'uuid', 'example': '00000000-0000-0000-0000-000000000000', 'minLength': 1, 'description': 'Identifier of either an interview definition (single-stage) or a position definition (multi-stage). The function resolves whichever matches.'}, 'conversation_id': {'type': 'string', 'description': "Pass the exact conversation_id from the server's previous response, unchanged. The server provides it on the first call â\x80\x94 never invent one, and do not issue parallel tool calls until you have it. Keep passing the same conversation_id for the rest of the conversation, including after later user messages or on a different task; do not reset it when the user starts a new request."}}}
输出模式
{'type': 'object', 'required': ['name', 'created_at', 'updated_at', 'questions', 'is_multistage', 'status', 'visibility', 'stage', 'type', 'environment', 'code', 'interview_location', 'cover_image_url', 'merchant_id', 'interview_template_id', 'interview_template_type', 'is_voice_only', 'knowledge_base_store_id', 'mojito_language_code', 'speech_language_code', 'speech_language_name', 'recording', 'recording_full_session', 'type_credit', 'result_view', 'candidate_video_introduction', 'description', 'interview_description_long', 'candidate_expectations', 'interview_department', 'interview_salary', 'interview_available_till', 'candidate_notification_channel', 'recruiter_profile_id', 'slug', 'tags', 'coach_plan', 'interview_conversation_speed', 'max_followups', 'max_duration', 'questions_random_subset', 'required_pronunciation', 'result_enable_edit_transcript'], 'properties': {'code': {'type': ['string', 'null'], 'description': 'Caller-supplied external code/reference.'}, 'name': {'type': ['string', 'null'], 'description': 'Interview or position name.'}, 'slug': {'type': ['string', 'null'], 'description': 'URL slug of the public listing, when one was generated.'}, 'tags': {'type': ['array', 'null'], 'items': {'type': 'string'}, 'example': ['interview-practice', 'sales'], 'description': 'Free-form tags. Also the coaching-catalogue mapping key: a catalogue directory lists this session when its `tags_interview_set_filter` is a subset of these tags. Null for multi-stage positions.'}, 'type': {'enum': ['coaching', 'interview', 'persona', 'persona_interview', 'public_avatar', 'assessment', None], 'type': ['string', 'null'], 'description': 'Interview type. Null for multi-stage positions.'}, 'stage': {'enum': ['Interest', 'Application submitted', 'Interview 1st planned', 'Interview 1st completed', 'Interview 2nd planned', 'Interview 2nd completed', 'Interview 3rd planned', 'Interview 3rd completed', 'Offer negotiations', 'Hired', 'Rejected', 'Offer declined', 'Other', None], 'type': ['string', 'null'], 'description': 'Hiring-pipeline stage. Null for multi-stage positions.'}, 'status': {'enum': ['draft', 'active', 'archived', 'deleted', 'preparing', 'completed', None], 'type': ['string', 'null'], 'description': 'Lifecycle status of the interview/position.'}, 'questions': {'type': ['array', 'null'], 'items': {'type': 'object', 'required': ['question'], 'properties': {'id': {'type': ['string', 'null'], 'description': "Identifier for this question. job-interview-get returns the question's real id here; send it back to job-interview-update so an unchanged question keeps its existing record (and with it its answer rules and any rendered avatar video). Also the handle another question references via conditional_question_main_id. On job-interview-create-from-array it is a caller-local value, only needed for those references."}, 'label': {'type': ['string', 'null'], 'description': 'Optional label/tag stored on the question.'}, 'duration': {'type': ['number', 'null'], 'description': 'Answer duration in seconds for this question.'}, 'question': {'type': ['string', 'null'], 'description': 'The question text shown to the candidate.'}, 'is_expert': {'type': ['boolean', 'null'], 'description': "Expert listening question (view 'with listening expert')."}, 'external_id': {'type': ['string', 'null'], 'description': 'External identifier stored on the question. job-interview-update matches on this first, so an ATS that owns stable ids can send its own array and have the diff line up without round-tripping our ids.'}, 'external_data': {'type': ['object', 'null'], 'description': 'Arbitrary JSON metadata stored on the question.', 'additionalProperties': {}}, 'is_conditional': {'type': ['boolean', 'null'], 'description': "Conditional follow-up question (view 'with listening conditional'). Use with conditional_question_main_id."}, 'knowledge_base_id': {'type': ['string', 'null'], 'description': 'Knowledge-base store id (uuid) the question draws context from.'}, 'is_multiple_choice': {'type': ['boolean', 'null'], 'description': "Multiple-choice question (view 'multiple choice')."}, 'is_without_scoring': {'type': ['boolean', 'null'], 'description': "Question is asked but not scored (view 'without scoring')."}, 'mojito_language_code': {'enum': ['ar', 'bg', 'zh', 'hr', 'cs', 'da', 'nl', 'en', 'fil', 'fi', 'fr', 'de', 'el', 'hi', 'hu', 'id', 'it', 'ja', 'ko', 'ms', 'no', 'pl', 'pt', 'br', 'ro', 'ru', 'sk', 'es', 'sv', 'ta', 'th', 'tr', 'uk', 'vi', None], 'type': ['string', 'null'], 'example': 'en', 'description': 'Per-question language override (one of the platform-languages.json codes). Inherits the interview language when omitted.'}, 'question_alternatives': {'type': ['array', 'null'], 'items': {'type': 'string'}, 'description': 'Alternative phrasings for the question.'}, 'candidate_expectations_json': {'type': ['object', 'null'], 'properties': {'weak': {'type': ['array', 'null'], 'items': {'type': 'string'}, 'description': 'Baseline requirements every viable candidate should meet (table stakes).'}, 'strong': {'type': ['array', 'null'], 'items': {'type': 'string'}, 'description': 'High-bar requirements only standout candidates clear.'}, 'moderate': {'type': ['array', 'null'], 'items': {'type': 'string'}, 'description': 'Requirements expected of a solid, competent candidate.'}}, 'description': 'Per-question candidate expectations, bucketed by requirement level (weak/moderate/strong). Extra keys are preserved.'}, 'conditional_question_main_id': {'type': ['string', 'null'], 'description': 'For a conditional question, the id (the "id" field above) of the parent question in this same array that triggers it. The parent must appear earlier in the array than the conditional question referencing it.'}, 'is_candidate_asking_recruiter': {'type': ['boolean', 'null'], 'description': "Candidate-asks-recruiter prompt (view 'candidate asking recruiter')."}}, 'additionalProperties': {}}, 'description': "The interview questions, in the order they are asked, in the same format job-interview-create-from-array accepts â\x80\x94 so this array can be edited and sent straight back to job-interview-update, or used to create a copy of this interview. Each `id` is the question's real identifier: send it back unchanged and the question keeps its existing record (and with it its answer rules and any rendered avatar video). The welcome, thank-you and instructional-video steps are NOT included â\x80\x94 they are not questions in this format, and job-interview-update leaves them untouched. Null for multi-stage positions, whose questions live on the individual interview stages."}, 'recording': {'enum': ['audio_first_5_answers', 'audio_all', 'video_all', 'video_first_5_answers', None], 'type': ['string', 'null'], 'description': 'Per-answer recording mode. Null for multi-stage positions.'}, 'coach_plan': {'enum': ['demo', 'screening', '2nd', '3rd', 'closing', 'job-specific', 'other', None], 'type': ['string', 'null'], 'description': 'Coaching-plan stage this session belongs to. Null for multi-stage positions and for sessions outside any plan.'}, 'created_at': {'type': ['string', 'null'], 'example': '2026-01-15T09:30:00.000Z'}, 'updated_at': {'type': ['string', 'null'], 'example': '2026-01-20T14:05:00.000Z'}, 'visibility': {'enum': ['public', 'merchant_public', 'merchant_invite', 'merchant_unlisted', 'sub_item', None], 'type': ['string', 'null'], 'description': 'Who can see and access the interview/position.'}, 'description': {'type': ['string', 'null'], 'description': 'Short description.'}, 'environment': {'enum': ['production', 'uat', 'development', 'demo', None], 'type': ['string', 'null'], 'example': 'production', 'description': "Which webhook environment this interview's results are delivered to. Null for multi-stage positions, whose stages each carry their own."}, 'merchant_id': {'type': ['string', 'null'], 'description': 'Owning merchant id.'}, 'result_view': {'enum': ['minimal', 'advanced', 'full', 'full_expand_scores', 'minimal_with_score', 'none', None], 'type': ['string', 'null'], 'description': 'Result view level. Null for multi-stage positions.'}, 'type_credit': {'enum': ['resume_check', 'interview_coach_starter', 'interview_coach_contributor', 'interview_coach_manager', 'cover_letter', None], 'type': ['string', 'null'], 'description': 'Credit bucket the interview draws from. Null for multi-stage positions.'}, 'max_duration': {'type': ['number', 'null'], 'description': 'Live session limit in seconds. Null for multi-stage positions.'}, 'is_multistage': {'type': ['boolean', 'null'], 'description': 'True when the id resolved to a multi-stage position rather than a single interview.'}, 'is_voice_only': {'type': ['boolean', 'null'], 'description': 'Convenience flag derived from interview_template_type: true when voice-only (`interactive_elevenlabs`), false when avatar-based, null when the template type could not be resolved.'}, 'max_followups': {'type': ['number', 'null'], 'description': 'Maximum number of AI follow-up questions; null uses the template default. Null for multi-stage positions.'}, 'result_scoring': {'description': 'Resolved result-scoring config (update field `custom_scoring`; its `max_retries` is the update field `interview_attempts`). Null means the platform defaults apply. Null for multi-stage positions.'}, 'cover_image_url': {'type': ['string', 'null'], 'description': 'Cover image URL.'}, 'interview_salary': {'type': ['string', 'null'], 'example': '$80k - $100k', 'description': 'Salary range shown for the position.'}, '_mcp_instructions': {'type': 'object', 'properties': {'conversation_id': {'type': 'string', 'description': 'The server-issued conversation identifier.'}}, 'description': 'Server-issued metadata for this conversation.'}, 'interview_location': {'type': ['string', 'null'], 'description': 'Location (create field `location`).'}, 'creation_parameters': {'description': 'The creation parameters recorded at build time (interview_type, interview_tone, interview_length, additional_context, include_rapport_question, include_closing_prompt, knowledge_base_store_id, seniority_level, hiring_for_company).'}, 'calc_definition_json': {'description': 'The compiled interview definition JSON (structure varies by interview type).'}, 'country_availability': {'description': "Portal availability by the candidate's country: {countries_allowed?: string[], countries_allowed_eu?: boolean, countries_blocked?: string[], countries_blocked_eu?: boolean} (ISO 3166-1 alpha-2, EU = EU + EEA + Switzerland; blocked wins), judged by the candidate's IP on the portal; invited candidates keep access. Null = not used, every country. Set it with job-interview-update."}, 'interview_department': {'type': ['string', 'null'], 'example': 'Engineering', 'description': 'Department the position belongs to.'}, 'mojito_language_code': {'type': ['string', 'null'], 'example': 'en', 'description': 'Platform (mojito) language code.'}, 'recruiter_profile_id': {'type': ['string', 'null'], 'description': 'Profile id of the recruiter owning this interview/position.'}, 'speech_language_code': {'type': ['string', 'null'], 'description': 'Azure speech language code. Null for multi-stage positions.'}, 'speech_language_name': {'type': ['string', 'null'], 'description': 'Azure speech language display name. Null for multi-stage positions.'}, 'interview_template_id': {'type': ['string', 'null'], 'description': "Interview template id. For multi-stage positions this is the first interview step's template."}, 'candidate_expectations': {'type': ['string', 'null'], 'description': 'Free-text candidate expectations. Null for multi-stage positions.'}, 'pdf_export_auto_config': {'description': 'Auto-PDF-report options applied when the interview completes; null when auto-export is off. Null for multi-stage positions.'}, 'recording_full_session': {'enum': ['audio_first_5_answers', 'audio_all', 'video_all', 'video_first_5_answers', None], 'type': ['string', 'null'], 'description': 'Full-session recording mode. Null for multi-stage positions.'}, 'required_pronunciation': {'type': ['boolean', 'null'], 'description': 'Whether a pronunciation assessment is required. Null for multi-stage positions.'}, 'interview_template_type': {'enum': ['offline_elai', 'offline_synthesia', 'interactive_heygen', 'offline_heygen', 'interactive_elevenlabs', 'interactive_spatius', None], 'type': ['string', 'null'], 'description': 'Type of the linked interview template. `interactive_elevenlabs` is voice-only; the others (`interactive_spatius`, `interactive_heygen`, `offline_heygen`, `offline_elai`, `offline_synthesia`) are avatar-based. Null when the template could not be resolved.'}, 'knowledge_base_store_id': {'type': ['string', 'null'], 'description': 'Linked knowledge base store id. Null for multi-stage positions.'}, 'questions_random_subset': {'type': ['number', 'null'], 'description': 'Fraction of the questions actually asked (0.01-0.9); null asks all of them. Null for multi-stage positions.'}, 'interview_available_till': {'type': ['string', 'null'], 'description': 'ISO date/time after which the interview is no longer available to candidates. Null means always available.'}, 'interview_description_long': {'type': ['string', 'null'], 'description': 'Long description (create/update field `description_long`). Rendered as Markdown on the candidate-facing position page â\x80\x94 formatting guide: https://developer.jobmojito.com/cookbooks/format-content-with-markdown'}, 'candidate_expectations_json': {'description': 'Structured candidate expectations JSON â\x80\x94 the scoring rubric. Null for multi-stage positions.'}, 'candidate_video_introduction': {'enum': ['hidden', 'optional', 'required', None], 'type': ['string', 'null'], 'description': 'Whether a candidate video introduction is hidden/optional/required. Null for multi-stage positions.'}, 'interview_conversation_speed': {'type': ['string', 'null'], 'description': 'Conversation pace of the AI avatar (slower/normal/faster). Null keeps the template default. Null for multi-stage positions.'}, 'result_enable_edit_transcript': {'type': ['boolean', 'null'], 'description': 'Whether the candidate may edit the transcript on the result view. Null for multi-stage positions.'}, 'candidate_notification_channel': {'enum': ['reminders', 'last_reminder', 'all', None], 'type': ['string', 'null'], 'description': 'SMS / WhatsApp candidate notifications: null = off, reminders = with both e-mail reminders, last_reminder = only with the final reminder, all = invitation + reminders + pre-screening accepted.'}}, 'x-fastmcp-top-level-schema': 'JobInterviewGetResponse'}
get_interview_result_details
Get interview result details
[Results] Get full interview result details including transcript and scores. Scores are assistive output for a human reviewer. One result is a large record, so `view` controls how much of it comes back — the default (`standard`) omits only the raw machine assessment data. Returns an interview result with its full transcript and AI assessment. Optionally attaches signed recording URLs.
只读 可访问外部资源 幂等
输入模式
{'type': 'object', 'required': ['interview_result_id'], 'properties': {'view': {'enum': ['summary', 'standard', 'full'], 'type': 'string', 'default': 'standard', 'description': "How much of the record to return. Handled by the MCP server, not the JobMojito API â\x80\x94 it only narrows the response, never the query.\n\n- `summary`: scores, the overall AI analysis, and each question with the candidate's answer â\x80\x94 no per-answer AI commentary, recording paths or raw assessment data. Use this to review or compare candidates.\n- `standard`: everything a human reviewer reads: the full transcript with per-answer analysis, scores and recordings, minus the raw machine assessment blobs. This is the default.\n- `full`: the API response verbatim, including the raw per-answer pronunciation/sentiment data. Large â\x80\x94 a long interview can exceed the result limit and fail. Only ask for this if you need those raw fields."}, 'conversation_id': {'type': 'string', 'description': "Pass the exact conversation_id from the server's previous response, unchanged. The server provides it on the first call â\x80\x94 never invent one, and do not issue parallel tool calls until you have it. Keep passing the same conversation_id for the rest of the conversation, including after later user messages or on a different task; do not reset it when the user starts a new request."}, 'interview_result_id': {'type': 'string', 'format': 'uuid', 'example': '93c98d21-e04d-4a84-9afa-ed154cf73636', 'minLength': 1, 'description': 'The interview result to fetch the transcript and details for.'}, 'get_signed_recordings': {'enum': ['true', 'false'], 'type': 'string', 'default': 'false', 'example': 'false', 'description': 'When true, includes short-lived signed recording URLs for the session, the video introduction, and each transcript answer.'}}}
输出模式
{'type': 'object', 'properties': {'end': {'type': ['string', 'null'], 'description': 'Interview end timestamp (training_end, ISO 8601).'}, 'score': {'type': ['number', 'null'], 'description': 'Overall interview score.'}, 'start': {'type': ['string', 'null'], 'description': 'Interview start timestamp (training_start, ISO 8601).'}, 'status': {'type': ['string', 'null'], 'description': 'Coach/interview status (coach_status), e.g. started, completed.'}, 'duration': {'type': ['number', 'null'], 'description': 'Total duration in deciseconds (duration_ds).'}, 'score_text': {'type': ['string', 'null'], 'description': 'Human-readable score summary.'}, 'transcript': {'type': ['array', 'null'], 'items': {'type': 'object', 'properties': {'id': {'type': ['string', 'null'], 'description': 'interview_result_question id.'}, 'view': {'type': ['string', 'null'], 'description': 'Question view/type (e.g. with listening, multiple choice, without scoring).'}, 'score': {'type': ['number', 'null'], 'description': 'Score for this interaction.'}, 'answer': {'type': ['string', 'null'], 'description': 'The candidate answer transcript text.'}, 'duration': {'type': ['number', 'null'], 'description': 'Duration of this interaction in deciseconds (duration_ds).'}, 'is_answer': {'type': ['boolean', 'null'], 'description': 'True for a candidate answer turn, false for an avatar/question turn.'}, 'ai_analysis': {'type': ['string', 'null'], 'description': 'AI analysis of this answer.'}, 'external_id': {'type': ['string', 'null'], 'description': 'External identifier carried from the question definition.'}, 'external_data': {'description': 'External data carried from the question definition.'}, 'recording_url': {'type': ['string', 'null'], 'description': 'Signed URL for recording_local_path; present only when get_signed_recordings=true.'}, 'question_asked': {'type': ['string', 'null'], 'description': 'The question text actually asked to the candidate.'}, 'score_answer_ai': {'type': ['number', 'null'], 'description': 'AI answer score.'}, 'score_simulation': {'type': ['number', 'null'], 'description': 'Simulated score for this interaction.'}, 'question_original': {'type': ['string', 'null'], 'description': 'Original question text from the definition (when question_original_id is set).'}, 'recording_is_video': {'type': ['boolean', 'null'], 'description': 'Whether this answer recording is video (vs audio).'}, 'mojito_language_code': {'type': ['string', 'null'], 'description': 'Platform language code of this interaction.'}, 'question_original_id': {'type': ['string', 'null'], 'description': 'Source interview_def_question id (null for generated follow-ups).'}, 'recording_local_path': {'type': ['string', 'null'], 'description': 'Storage path of this answer recording (private-recordings bucket).'}, 'ai_analysis_recruiter': {'type': ['string', 'null'], 'description': 'Recruiter-facing AI analysis of this answer.'}, 'answer_assessment_raw_data': {'description': 'Raw per-answer assessment data (pronunciation/sentiment/etc.).'}, 'score_answer_ai_simulation': {'type': ['number', 'null'], 'description': 'Simulated AI answer score.'}}, 'additionalProperties': {}}, 'description': 'Ordered interactions (questions + answers) of the interview.'}, 'ai_analysis': {'type': ['string', 'null'], 'description': 'Candidate-facing AI analysis of the whole interview.'}, 'score_answer': {'type': ['number', 'null'], 'description': 'Aggregate answer sub-score.'}, 'recording_url': {'type': ['string', 'null'], 'description': 'Signed session-recording URL; present only when get_signed_recordings=true.'}, 'recruiter_risks': {'description': 'Detected recruiter risk flags (jsonb).'}, 'score_sentiment': {'type': ['number', 'null'], 'description': 'Sentiment sub-score.'}, 'score_simulation': {'type': ['number', 'null'], 'description': 'Overall simulated score.'}, '_mcp_instructions': {'type': 'object', 'properties': {'conversation_id': {'type': 'string', 'description': 'The server-issued conversation identifier.'}}, 'description': 'Server-issued metadata for this conversation.'}, 'ai_analysis_other': {'description': 'Session-level AI analyses keyed by analysis name (jsonb). `strengths_concerns`: { strengths: string[], concerns: string[] } (0-4 items each, recruiter-facing; called `hiring_reasons` with `reasons_to_hire` / `reasons_not_to_hire` inside before 2026-09-15, and rows written before then may still carry that shape). `takeaways`: { what_went_well: string[], next_steps: { text, priority: impact | quick | longterm, guidance: { kind: say | structure | length | exercise | perspective, text }, proof? }[], fixed?: string[] } (coaching / persona sessions, learner-facing; `proof` entries are { kind: quote | ai_summary | transcript_ref | document, text, ref?: { result_question_id } }; `fixed` lists the steps from the previous attempt that the learner did this time). `multi_department`: the multi-department-selection analysis. `score_rationale`: the rubric bracket of the session score and evidenced counts. `key_statement`: { quote, result_question_id }, the one verbatim quotation a recruiter would remember the candidate by (interview / persona_interview, absent when nothing distinctive was said). Further keys may be added.'}, 'recording_is_video': {'type': ['boolean', 'null'], 'description': 'Whether the session recording is video.'}, 'score_pronunciation': {'type': ['number', 'null'], 'description': 'Pronunciation sub-score.'}, 'ai_completion_reason': {'type': ['string', 'null'], 'description': 'Why the interview completed (ai_completed_reason).'}, 'recording_local_path': {'type': ['string', 'null'], 'description': 'Storage path of the full session recording.'}, 'ai_analysis_recruiter': {'type': ['string', 'null'], 'description': 'Recruiter-facing AI analysis of the whole interview.'}, 'score_words_per_minute': {'type': ['number', 'null'], 'description': 'Speaking-pace (words per minute) sub-score.'}, 'video_introduction_url': {'type': ['string', 'null'], 'description': 'Signed video-introduction URL; present only when get_signed_recordings=true.'}, 'user_feedback_recruiter': {'type': ['string', 'null'], 'description': 'Recruiter-entered feedback note.'}, 'video_introduction_local_path': {'type': ['string', 'null'], 'description': 'Storage path of the candidate video introduction.'}, 'ai_analysis_recruiter_why_hire': {'description': 'Reasons to hire (list). Deprecated: a copy of ai_analysis_other.strengths_concerns.strengths, kept for existing integrations.'}, 'ai_interview_coverage_percentage': {'type': ['number', 'null'], 'description': 'Percentage of the intended interview the AI judged to be covered.'}, 'ai_analysis_recruiter_why_not_hire': {'description': 'Reasons not to hire (list). Deprecated: a copy of ai_analysis_other.strengths_concerns.concerns, kept for existing integrations.'}}, 'description': 'The interview result with its transcript, produced by the interview_transcript RPC. Additional fields may be present (passthrough).', 'additionalProperties': {}, 'x-fastmcp-top-level-schema': 'JobInterviewDetailsResponse'}
get_merchant_analytics
Get merchant analytics
[Results] Get the merchant's daily event analytics. Daily event-count time-series for a merchant over a date range (the admin-portal analytics events graph), scoped to your token's merchant (or a merchant_id override). Optionally drilled to a single interview. Capped at 1000 records per page. Note: only day/event combinations with a non-zero count are returned — any day/event pair absent from the response should be treated as a count of 0 by the caller.
只读 可访问外部资源 幂等
输入模式
{'type': 'object', 'required': ['date_from', 'date_to'], 'properties': {'limit': {'type': 'integer', 'default': 50, 'example': 50, 'maximum': 1000.0, 'minimum': 1.0, 'description': 'Maximum number of records to return (1â\x80\x931000).'}, 'offset': {'type': 'integer', 'default': 0, 'example': 0, 'minimum': 0.0, 'description': 'Number of records to skip from the start of the result set.'}, 'date_to': {'type': 'string', 'example': '2026-01-01', 'pattern': '^\\d{4}-\\d{2}-\\d{2}$', 'description': 'End of the date range (inclusive), YYYY-MM-DD.'}, 'date_from': {'type': 'string', 'example': '2026-01-01', 'pattern': '^\\d{4}-\\d{2}-\\d{2}$', 'description': 'Start of the date range (inclusive), YYYY-MM-DD.'}, 'merchant_id': {'type': 'string', 'format': 'uuid', 'example': '28106cba-1c27-4e53-b149-32113e5e8e31', 'description': "Optional merchant to scope to. Admins and sub-merchant operators only; other callers always use their token's merchant."}, 'interview_id': {'type': 'string', 'format': 'uuid', 'description': 'Optional interview (interview_def_set) or position (position_def_set) id to drill the event counts down. The type is detected automatically: a position aggregates the daily counts across every interview that makes up the position; an interview filters to that single definition.'}, 'conversation_id': {'type': 'string', 'description': "Pass the exact conversation_id from the server's previous response, unchanged. The server provides it on the first call â\x80\x94 never invent one, and do not issue parallel tool calls until you have it. Keep passing the same conversation_id for the rest of the conversation, including after later user messages or on a different task; do not reset it when the user starts a new request."}}}
输出模式
{'type': 'object', 'required': ['data', 'pagination'], 'properties': {'data': {'type': ['array', 'null'], 'items': {'type': 'object', 'required': ['day', 'event', 'event_number'], 'properties': {'day': {'type': ['string', 'null'], 'example': '2026-01-15', 'description': 'Calendar day (YYYY-MM-DD).'}, 'event': {'type': ['string', 'null'], 'description': 'Event type (e.g. interview, interview_invitation, interview_page_visit).'}, 'event_number': {'type': ['number', 'null'], 'example': 12, 'description': 'Count of this event on this day. Always greater than 0 â\x80\x94 zero-count day/event combinations are omitted.'}}, 'additionalProperties': {}}, 'description': 'Daily event counts for the requested range, ordered by day ascending. Only day/event combinations with a non-zero count are returned; missing combinations should be treated as 0 by the caller.'}, 'pagination': {'type': 'object', 'required': ['total', 'limit', 'offset', 'has_more'], 'properties': {'limit': {'type': ['integer', 'null'], 'example': 50, 'description': 'Page size used for this response.'}, 'total': {'type': ['integer', 'null'], 'example': 137, 'description': 'Total matching records across all pages.'}, 'offset': {'type': ['integer', 'null'], 'example': 0, 'description': 'Offset used for this response.'}, 'has_more': {'type': ['boolean', 'null'], 'example': True, 'description': 'True when more records exist beyond this page (offset + returned < total).'}}}, '_mcp_instructions': {'type': 'object', 'properties': {'conversation_id': {'type': 'string', 'description': 'The server-issued conversation identifier.'}}, 'description': 'Server-issued metadata for this conversation.'}}, 'x-fastmcp-top-level-schema': 'MerchantAnalyticsResponse'}
get_merchant_credit_usage
Get merchant credit usage
[Results] Get the merchant's credit usage. Per-event credit-usage ledger for a merchant: every billable analytics event (interview, pre-screening, public avatar, simulation, …) that consumed credits, ordered most recent first. Scoped to your token's merchant, or a merchant_id override for admins / sub-merchant operators. The credits consumed by each event are in stats.credit_amount. Capped at 1000 records per page.
只读 可访问外部资源 幂等
输入模式
{'type': 'object', 'required': [], 'properties': {'limit': {'type': 'integer', 'default': 50, 'example': 50, 'maximum': 1000.0, 'minimum': 1.0, 'description': 'Maximum number of records to return (1â\x80\x931000).'}, 'offset': {'type': 'integer', 'default': 0, 'example': 0, 'minimum': 0.0, 'description': 'Number of records to skip from the start of the result set.'}, 'merchant_id': {'type': 'string', 'format': 'uuid', 'example': '28106cba-1c27-4e53-b149-32113e5e8e31', 'description': "Optional merchant to scope to. Admins and sub-merchant operators only; other callers always use their token's merchant."}, 'interview_id': {'type': 'string', 'format': 'uuid', 'description': "Optional interview (interview_def_set) or position (position_def_set) id to drill the credit-usage ledger down to a single interview or position. The type is detected automatically: for a position the response combines pre-screening and interview-result credits across the whole position; for an interview it returns that interview's credit events (including simulations and report translations)."}, 'conversation_id': {'type': 'string', 'description': "Pass the exact conversation_id from the server's previous response, unchanged. The server provides it on the first call â\x80\x94 never invent one, and do not issue parallel tool calls until you have it. Keep passing the same conversation_id for the rest of the conversation, including after later user messages or on a different task; do not reset it when the user starts a new request."}}}
输出模式
{'type': 'object', 'required': ['data', 'pagination'], 'properties': {'data': {'type': ['array', 'null'], 'items': {'type': 'object', 'required': ['id', 'event_date', 'event', 'credit_amount', 'candidate_name', 'profile_id', 'profile_interview_id', 'object_uuid', 'parent_object_uuid'], 'properties': {'id': {'type': ['string', 'null'], 'format': 'uuid', 'description': 'Analytics event id.'}, 'event': {'type': ['string', 'null'], 'example': 'interview', 'description': 'Billable event type that consumed the credit (e.g. interview, interview_reviewing, interview_failed, interview_incomplete, pre_screening, candidate_report_translation, candidate_kyc, public_avatar, interview_simulation).'}, 'stats': {'description': 'Event stats JSON. Contains credit_amount (the credits consumed by this event) plus event-specific fields.'}, 'event_date': {'type': ['string', 'null'], 'example': '2026-01-15T09:30:00.000Z', 'description': 'When the credit-consuming event occurred (ISO 8601).'}, 'profile_id': {'type': ['string', 'null'], 'format': 'uuid', 'description': 'Underlying person (profile) id, when linked.'}, 'object_uuid': {'type': ['string', 'null'], 'format': 'uuid', 'description': 'Primary object the event refers to (e.g. the interview result / attempt).'}, 'credit_amount': {'type': ['number', 'null'], 'example': 1, 'description': 'Number of credits deducted by this event, surfaced from stats.credit_amount for convenience. Null when the amount is absent.'}, 'candidate_name': {'type': ['string', 'null'], 'description': 'Candidate display name from the linked profile interview, when available.'}, 'parent_object_uuid': {'type': ['string', 'null'], 'format': 'uuid', 'description': 'Parent object of the event (e.g. the interview definition), when applicable.'}, 'profile_interview_id': {'type': ['string', 'null'], 'format': 'uuid', 'description': 'Candidate enrolment (profile interview) id, when linked.'}}, 'additionalProperties': {}}, 'description': 'Credit-consuming analytics events for the merchant, most recent first. Each row is one billable event; the credits it consumed are in stats.credit_amount.'}, 'pagination': {'type': 'object', 'required': ['total', 'limit', 'offset', 'has_more'], 'properties': {'limit': {'type': ['integer', 'null'], 'example': 50, 'description': 'Page size used for this response.'}, 'total': {'type': ['integer', 'null'], 'example': 137, 'description': 'Total matching records across all pages.'}, 'offset': {'type': ['integer', 'null'], 'example': 0, 'description': 'Offset used for this response.'}, 'has_more': {'type': ['boolean', 'null'], 'example': True, 'description': 'True when more records exist beyond this page (offset + returned < total).'}}}, '_mcp_instructions': {'type': 'object', 'properties': {'conversation_id': {'type': 'string', 'description': 'The server-issued conversation identifier.'}}, 'description': 'Server-issued metadata for this conversation.'}}, 'x-fastmcp-top-level-schema': 'MerchantCreditsUsedResponse'}
get_merchant_status
Get merchant status
[Admin] Get a merchant status snapshot: credit balances, subscription, pending-work counts, candidate/result totals, and invitation headroom. Status snapshot for a merchant: interview-credit balances, subscription type/status, pending-work counts (undecided / ongoing / uncredited interviews), candidate & result totals with 14-day history, and invitation headroom. Scoped to your token's merchant (or a merchant_id override for admins / sub-merchant operators). Also echoes the caller's profile_id and default_merchant_id from the token, plus the effective merchant_id.
只读 可访问外部资源 幂等
输入模式
{'type': 'object', 'required': [], 'properties': {'merchant_id': {'type': 'string', 'format': 'uuid', 'example': '28106cba-1c27-4e53-b149-32113e5e8e31', 'description': "Optional merchant to scope to. Admins and sub-merchant operators only; other callers always use their token's merchant."}, 'conversation_id': {'type': 'string', 'description': "Pass the exact conversation_id from the server's previous response, unchanged. The server provides it on the first call â\x80\x94 never invent one, and do not issue parallel tool calls until you have it. Keep passing the same conversation_id for the rest of the conversation, including after later user messages or on a different task; do not reset it when the user starts a new request."}}}
输出模式
{'type': 'object', 'required': ['profile_id', 'default_merchant_id', 'merchant_id', 'credits_interview_monthly', 'credits_interview_monthly_limit', 'credits_interview_extra', 'credits_interview_single', 'definitions_active', 'interviews_without_credits', 'interviews_undecided', 'interviews_ongoing', 'interview_results', 'candidates', 'candidates_history', 'interview_result_history', 'subscription_type', 'subscription_status', 'invitations_sent', 'invitations_limit', 'invitations_available'], 'properties': {'candidates': {'type': ['number', 'null'], 'example': 212, 'description': 'Total candidates (non-archived profile_interview rows) for the merchant.'}, 'profile_id': {'type': ['string', 'null'], 'example': '9b2c1e54-7a3d-4f8e-9c10-2b6a4d5e7f01', 'description': "The calling user's profile id (auth user id), taken from the JWT."}, 'merchant_id': {'type': ['string', 'null'], 'example': '28106cba-1c27-4e53-b149-32113e5e8e31', 'description': 'The merchant this status is scoped to â\x80\x94 the default_merchant_id unless an admin / sub-merchant operator overrode it via the merchant_id query param.'}, 'invitations_sent': {'type': ['number', 'null'], 'example': 18, 'description': 'Interview invitations sent during the current subscription period.'}, '_mcp_instructions': {'type': 'object', 'properties': {'conversation_id': {'type': 'string', 'description': 'The server-issued conversation identifier.'}}, 'description': 'Server-issued metadata for this conversation.'}, 'interview_results': {'type': ['number', 'null'], 'example': 137, 'description': 'Total non-archived interview results for the merchant.'}, 'invitations_limit': {'type': ['number', 'null'], 'example': 40, 'description': 'Maximum invitations allowed this period (4x available credits). Null for unlimited (Special) plans.'}, 'subscription_type': {'type': ['string', 'null'], 'example': 'Growth', 'description': 'Subscription plan name (e.g. Free, Starter, Growth, Special).'}, 'candidates_history': {'type': ['array', 'null'], 'items': {'type': 'number'}, 'example': [3, 5, 0, 2, 8, 1, 0, 4, 6, 2, 1, 0, 3, 5], 'description': 'Daily new-candidate counts for the last 14 days, most recent first.'}, 'definitions_active': {'type': ['number', 'null'], 'example': 4, 'description': 'Count of active interview + position definitions.'}, 'interviews_ongoing': {'type': ['number', 'null'], 'example': 1, 'description': 'Interviews currently in progress (coach_status = started).'}, 'default_merchant_id': {'type': ['string', 'null'], 'example': '28106cba-1c27-4e53-b149-32113e5e8e31', 'description': "The caller's home merchant id pinned in the JWT (app_metadata.merchant_id). Null if the token carries no merchant."}, 'subscription_status': {'type': ['string', 'null'], 'example': 'active', 'description': 'Subscription status (e.g. active, past_due, canceled). Null when no subscription.'}, 'interviews_undecided': {'type': ['number', 'null'], 'example': 3, 'description': 'Completed interviews awaiting a recruiter decision.'}, 'invitations_available': {'type': ['number', 'null'], 'example': 22, 'description': 'Remaining invitations this period. Null for unlimited (Special) plans.'}, 'credits_interview_extra': {'type': ['number', 'null'], 'example': 25, 'description': 'Extra (top-up) interview credits available on top of the monthly allowance.'}, 'credits_interview_single': {'type': ['number', 'null'], 'example': 0, 'description': 'Single-position interview credits available.'}, 'interview_result_history': {'type': ['array', 'null'], 'items': {'type': 'number'}, 'example': [1, 2, 0, 1, 3, 0, 0, 2, 1, 1, 0, 0, 1, 2], 'description': 'Daily new-interview-result counts for the last 14 days, most recent first.'}, 'credits_interview_monthly': {'type': ['number', 'null'], 'example': 8, 'description': 'Remaining monthly interview credits.'}, 'interviews_without_credits': {'type': ['number', 'null'], 'example': 2, 'description': 'Completed interviews that have not yet consumed a credit.'}, 'credits_interview_monthly_limit': {'type': ['number', 'null'], 'example': 10, 'description': 'Monthly interview-credit allowance for the current plan.'}}, 'additionalProperties': {}, 'x-fastmcp-top-level-schema': 'MerchantStatus'}
jobmojito_configuration
Choose a JobMojito merchant
Show the interactive JobMojito merchant picker (UI). ALWAYS call this when the user wants to choose, switch, or set a merchant, or when a tool needs a `merchant_id` and none is selected. It renders a searchable picker with clickable options. Do NOT list merchants as text or ask the user to type a name — render this picker instead. After calling it, STOP and wait for the user's selection; then pass `merchant_id=<chosen id>` on every JobMojito call (omit it for the user's own account).
只读 幂等
输入模式
{'type': 'object', 'properties': {'conversation_id': {'type': 'string', 'description': "Pass the exact conversation_id from the server's previous response, unchanged. The server provides it on the first call â\x80\x94 never invent one, and do not issue parallel tool calls until you have it. Keep passing the same conversation_id for the rest of the conversation, including after later user messages or on a different task; do not reset it when the user starts a new request."}}, 'additionalProperties': False}
list_avatars
List avatars and voice templates
[Admin] List available avatar/voice templates. Each item's `type` decides the interview modality: `interactive_elevenlabs` = voice-only (no video avatar); `interactive_spatius` = realtime interactive 3D avatar (rendered in the candidate's browser, 1.25 credits, no early stop); `interactive_heygen` = premium realtime interactive video avatar; `offline_heygen` = pre-recorded, non-interactive avatar. An item's `id` is the `interview_template_id` you pass to the create-interview tools, so pick the template whose type matches the experience you want. Note: `offline_elai` and `offline_synthesia` are legacy integrations that may still appear here but cannot be used to create new interviews. Rows are large, so this returns 15 at a time; page with `offset` while `pagination.has_more` is true, or narrow with `type`/`filter_text`. Paginated list of a merchant's avatar templates (the admin-portal avatars list), scoped to your token's merchant (or a merchant_id override). Capped at 1000 records per page.
只读 可访问外部资源 幂等
输入模式
{'type': 'object', 'required': [], 'properties': {'type': {'enum': ['interactive_heygen', 'interactive_elevenlabs', 'interactive_spatius', 'offline_heygen', 'offline_elai', 'offline_synthesia'], 'type': 'string', 'example': 'interactive_heygen', 'description': 'Filter by avatar template type. Omit for all.'}, 'limit': {'type': 'integer', 'default': 15, 'example': 50, 'maximum': 1000.0, 'minimum': 1.0, 'description': 'Maximum number of records to return (1â\x80\x931000).'}, 'offset': {'type': 'integer', 'default': 0, 'example': 0, 'minimum': 0.0, 'description': 'Number of records to skip from the start of the result set.'}, 'status': {'enum': ['active', 'draft', 'archived', 'deleted'], 'type': 'string', 'example': 'active', 'description': 'Filter by status. Omit for all except archived (see include_archived).'}, 'filter_text': {'type': 'string', 'description': 'Case-insensitive search on template name or voice language name.'}, 'merchant_id': {'type': 'string', 'format': 'uuid', 'example': '28106cba-1c27-4e53-b149-32113e5e8e31', 'description': "Optional merchant to scope to. Admins and sub-merchant operators only; other callers always use their token's merchant."}, 'include_public': {'enum': ['true', 'false'], 'type': 'string', 'default': 'false', 'example': 'false', 'description': "Also include public templates shared across merchants, in addition to this merchant's own."}, 'conversation_id': {'type': 'string', 'description': "Pass the exact conversation_id from the server's previous response, unchanged. The server provides it on the first call â\x80\x94 never invent one, and do not issue parallel tool calls until you have it. Keep passing the same conversation_id for the rest of the conversation, including after later user messages or on a different task; do not reset it when the user starts a new request."}, 'include_archived': {'enum': ['true', 'false'], 'type': 'string', 'default': 'false', 'example': 'false', 'description': 'Include archived templates (excluded by default).'}, 'mojito_language_code': {'enum': ['ar', 'bg', 'zh', 'hr', 'cs', 'da', 'nl', 'en', 'fil', 'fi', 'fr', 'de', 'el', 'hi', 'hu', 'id', 'it', 'ja', 'ko', 'ms', 'no', 'pl', 'pt', 'br', 'ro', 'ru', 'sk', 'es', 'sv', 'ta', 'th', 'tr', 'uk', 'vi'], 'type': 'string', 'example': 'en', 'description': 'Filter by platform language code. Omit for all languages.'}}}
输出模式
{'type': 'object', 'required': ['data', 'pagination'], 'properties': {'data': {'type': ['array', 'null'], 'items': {'type': 'object', 'required': ['id'], 'properties': {'id': {'type': ['string', 'null'], 'description': 'Avatar template id.'}, 'name': {'type': ['string', 'null'], 'description': 'Template name.'}, 'type': {'type': ['string', 'null'], 'description': 'Avatar template type.'}, 'status': {'type': ['string', 'null'], 'description': 'Status (active/draft/archived/deleted).'}, 'media_url': {'type': ['string', 'null'], 'description': 'Avatar media URL.'}, 'created_at': {'type': ['string', 'null'], 'description': 'Creation timestamp (ISO 8601).'}, 'updated_at': {'type': ['string', 'null'], 'description': 'Last update timestamp (ISO 8601).'}, 'visibility': {'type': ['string', 'null'], 'description': 'Visibility (public/merchant_â\x80¦).'}, 'merchant_id': {'type': ['string', 'null'], 'description': 'Owning merchant id.'}, 'background_url': {'type': ['string', 'null'], 'description': 'Background image URL.'}, 'background_blur': {'type': ['number', 'null'], 'description': 'Background blur intensity (0â\x80\x931); higher is blurrier.'}, 'mojito_language_code': {'type': ['string', 'null'], 'description': 'Platform language code.'}, 'video_avatar_image_url': {'type': ['string', 'null'], 'description': 'Avatar still-image URL.'}, 'video_background_remove': {'type': ['boolean', 'null'], 'description': 'Whether the video background is removed.'}, 'video_avatar_aspect_ratio': {'type': ['string', 'null'], 'description': 'Avatar aspect ratio.'}, 'video_voice_language_name': {'type': ['string', 'null'], 'description': 'Voice language display name.'}}, 'additionalProperties': {}}, 'description': "The merchant's avatar templates for this page, newest-updated first."}, 'pagination': {'type': 'object', 'required': ['total', 'limit', 'offset', 'has_more'], 'properties': {'limit': {'type': ['integer', 'null'], 'example': 50, 'description': 'Page size used for this response.'}, 'total': {'type': ['integer', 'null'], 'example': 137, 'description': 'Total matching records across all pages.'}, 'offset': {'type': ['integer', 'null'], 'example': 0, 'description': 'Offset used for this response.'}, 'has_more': {'type': ['boolean', 'null'], 'example': True, 'description': 'True when more records exist beyond this page (offset + returned < total).'}}}, '_mcp_instructions': {'type': 'object', 'properties': {'conversation_id': {'type': 'string', 'description': 'The server-issued conversation identifier.'}}, 'description': 'Server-issued metadata for this conversation.'}}, 'x-fastmcp-top-level-schema': 'MerchantAvatarListResponse'}
list_candidates
List candidates
[Candidates] List the merchant's candidates. Paginated list of a merchant's candidates (the admin-portal candidates list), scoped to your token's merchant (or a merchant_id override). Capped at 1000 records per page.
只读 可访问外部资源 幂等
输入模式
{'type': 'object', 'required': [], 'properties': {'tab': {'enum': ['interview', 'pre-screening', 'no-action', 'leads', ''], 'type': 'string', 'example': 'interview', 'description': 'Filter candidates by recent activity. Omit (or empty) to include all.'}, 'limit': {'type': 'integer', 'default': 50, 'example': 50, 'maximum': 1000.0, 'minimum': 1.0, 'description': 'Maximum number of records to return (1â\x80\x931000).'}, 'offset': {'type': 'integer', 'default': 0, 'example': 0, 'minimum': 0.0, 'description': 'Number of records to skip from the start of the result set.'}, 'source': {'enum': ['invited', 'registered'], 'type': 'string', 'example': 'registered', 'description': 'Filter by how the candidate entered: invited or self-registered. Omit for both.'}, 'order_by': {'enum': ['name_accending', 'name_decending', 'created_at_newest', 'created_at_oldest'], 'type': 'string', 'default': 'created_at_newest', 'example': 'created_at_newest', 'description': 'Sort order of the result set.'}, 'filter_text': {'type': 'string', 'description': 'Search on candidate name, email, external id, phone and CV skills. Every word must match (case and accents ignored; longer words tolerate typos). Without order_by, the best matches come first.'}, 'merchant_id': {'type': 'string', 'format': 'uuid', 'example': '28106cba-1c27-4e53-b149-32113e5e8e31', 'description': "Optional merchant to scope to. Admins and sub-merchant operators only; other callers always use their token's merchant."}, 'filter_emoji': {'type': 'string', 'description': 'Filter by the candidate emoji marker.'}, 'conversation_id': {'type': 'string', 'description': "Pass the exact conversation_id from the server's previous response, unchanged. The server provides it on the first call â\x80\x94 never invent one, and do not issue parallel tool calls until you have it. Keep passing the same conversation_id for the rest of the conversation, including after later user messages or on a different task; do not reset it when the user starts a new request."}}}
输出模式
{'type': 'object', 'required': ['data', 'pagination'], 'properties': {'data': {'type': ['array', 'null'], 'items': {'type': 'object', 'required': ['id'], 'properties': {'id': {'type': ['string', 'null'], 'description': 'Candidate (profile_interview) id.'}, 'name': {'type': ['string', 'null'], 'description': 'Candidate name.'}, 'email': {'type': ['string', 'null'], 'description': 'Candidate email.'}, 'emoji': {'type': ['string', 'null'], 'description': 'Emoji marker.'}, 'skills': {'type': ['array', 'null'], 'items': {'type': 'string'}, 'description': "Skills read from the candidate's latest CV; null until extracted."}, 'status': {'type': ['string', 'null'], 'description': 'Status (active/invited/deleted).'}, 'linked_in': {'type': ['string', 'null'], 'description': 'LinkedIn URL.'}, 'avatar_url': {'type': ['string', 'null'], 'description': 'Avatar image URL.'}, 'created_at': {'type': ['string', 'null'], 'description': 'Creation timestamp (ISO 8601).'}, 'deleted_at': {'type': ['string', 'null'], 'description': 'Deletion timestamp (ISO 8601), if deleted.'}, 'email_auth': {'type': ['string', 'null'], 'description': 'Auth email (login).'}, 'profile_id': {'type': ['string', 'null'], 'description': 'Underlying profile id.'}, 'updated_at': {'type': ['string', 'null'], 'description': 'Last update timestamp (ISO 8601).'}, 'external_id': {'type': ['string', 'null'], 'description': 'External identifier.'}, 'merchant_id': {'type': ['string', 'null'], 'description': 'Owning merchant id.'}, 'phone_number': {'type': ['string', 'null'], 'description': 'Phone number.'}, 'last_login_at': {'type': ['string', 'null'], 'description': 'Last login timestamp (ISO 8601).'}, 'interview_last': {'type': ['string', 'null'], 'description': 'Most recent interview timestamp (ISO 8601).'}, 'interview_count': {'type': ['number', 'null'], 'description': 'Number of interviews taken.'}, 'physical_address': {'type': ['string', 'null'], 'description': 'Physical address.'}, 'avatar_local_path': {'type': ['string', 'null'], 'description': 'Avatar storage path.'}, 'pre_screening_count': {'type': ['number', 'null'], 'description': 'Number of pre-screenings taken.'}, 'public_avatar_count': {'type': ['number', 'null'], 'description': 'Number of public-avatar conversations.'}, 'kyc_image_local_path': {'type': ['string', 'null'], 'description': 'KYC image storage path.'}, 'mojito_language_code': {'type': ['string', 'null'], 'description': 'Platform language code.'}, 'kyc_processing_status': {'type': ['string', 'null'], 'description': 'KYC processing status.'}}, 'additionalProperties': {}}, 'description': "The merchant's candidates for this page."}, 'pagination': {'type': 'object', 'required': ['total', 'limit', 'offset', 'has_more'], 'properties': {'limit': {'type': ['integer', 'null'], 'example': 50, 'description': 'Page size used for this response.'}, 'total': {'type': ['integer', 'null'], 'example': 137, 'description': 'Total matching records across all pages.'}, 'offset': {'type': ['integer', 'null'], 'example': 0, 'description': 'Offset used for this response.'}, 'has_more': {'type': ['boolean', 'null'], 'example': True, 'description': 'True when more records exist beyond this page (offset + returned < total).'}}}, '_mcp_instructions': {'type': 'object', 'properties': {'conversation_id': {'type': 'string', 'description': 'The server-issued conversation identifier.'}}, 'description': 'Server-issued metadata for this conversation.'}}, 'x-fastmcp-top-level-schema': 'MerchantCandidateListResponse'}
list_catalogue_directories
List coaching catalogue directories
[Coaching catalogue] List the coaching-catalogue directories you can see (your merchant's own plus the platform-wide public ones). Start here to find a directory id, to pick a parent for a new one, or to walk the tree with `parent_tag`; `is_start_directory` marks the page the catalogue opens on. The custom Markdown page is not included — read it with get_catalogue_directory. Returns 25 at a time; page with `offset` while `pagination.has_more` is true. Paginated list of the coaching-catalogue directories visible to you: your merchant's own, plus the platform-wide `public` ones unless you set include_public=false. Use it to find a directory id before updating one, to pick a `parent_tag`, or to walk the tree with `parent_tag`. The custom Markdown page is not included — fetch it per directory with catalogue-tag-get.
只读 可访问外部资源 幂等
输入模式
{'type': 'object', 'required': [], 'properties': {'limit': {'type': 'integer', 'default': 25, 'example': 50, 'maximum': 1000.0, 'minimum': 1.0, 'description': 'Maximum number of records to return (1â\x80\x931000).'}, 'offset': {'type': 'integer', 'default': 0, 'example': 0, 'minimum': 0.0, 'description': 'Number of records to skip from the start of the result set.'}, 'status': {'enum': ['draft', 'active', 'archived'], 'type': 'string', 'example': 'active', 'description': 'Filter by lifecycle status. Omit to include every status you can see (deleted directories are never returned).'}, 'parent_tag': {'type': 'string', 'description': "Return only the directories nested directly under this one (its `tags_sub`), in the parent's own order. Combine with the other filters to narrow further."}, 'visibility': {'enum': ['public', 'merchant_public', 'merchant_invite', 'merchant_unlisted'], 'type': 'string', 'example': 'merchant_public', 'description': 'Filter by visibility.'}, 'filter_text': {'type': 'string', 'description': 'Case-insensitive search on the directory id, name and description.'}, 'merchant_id': {'type': 'string', 'format': 'uuid', 'example': '28106cba-1c27-4e53-b149-32113e5e8e31', 'description': "Optional merchant to scope to. Admins and sub-merchant operators only; other callers always use their token's merchant."}, 'include_public': {'enum': ['true', 'false'], 'type': 'string', 'default': 'true', 'example': 'true', 'description': 'Include the platform-wide `public` directories shared across merchants.'}, 'conversation_id': {'type': 'string', 'description': "Pass the exact conversation_id from the server's previous response, unchanged. The server provides it on the first call â\x80\x94 never invent one, and do not issue parallel tool calls until you have it. Keep passing the same conversation_id for the rest of the conversation, including after later user messages or on a different task; do not reset it when the user starts a new request."}, 'mojito_language_code': {'enum': ['ar', 'bg', 'zh', 'hr', 'cs', 'da', 'nl', 'en', 'fil', 'fi', 'fr', 'de', 'el', 'hi', 'hu', 'id', 'it', 'ja', 'ko', 'ms', 'no', 'pl', 'pt', 'br', 'ro', 'ru', 'sk', 'es', 'sv', 'ta', 'th', 'tr', 'uk', 'vi'], 'type': 'string', 'example': 'en', 'description': 'Filter by the directory language. Omit for all languages.'}}}
输出模式
{'type': 'object', 'required': ['data', 'pagination'], 'properties': {'data': {'type': ['array', 'null'], 'items': {'type': 'object', 'required': ['id', 'has_content_page', 'is_start_directory'], 'properties': {'id': {'type': ['string', 'null'], 'example': 'sales-coaching-en', 'description': "Directory id â\x80\x94 also the catalogue URL segment and the value referenced in a parent's `tags_sub`."}, 'name': {'type': ['string', 'null'], 'description': 'Display name.'}, 'status': {'type': ['string', 'null'], 'description': 'Lifecycle status (draft/active/archived).'}, 'tags_sub': {'type': ['array', 'null'], 'items': {'type': 'string'}, 'description': 'Ids of the directories nested under this one, in display order.'}, 'coach_plan': {'type': ['string', 'null'], 'description': 'Coaching-plan stage, when the directory belongs to one.'}, 'created_at': {'type': ['string', 'null'], 'description': 'Creation timestamp (ISO 8601).'}, 'updated_at': {'type': ['string', 'null'], 'description': 'Last update timestamp (ISO 8601).'}, 'visibility': {'type': ['string', 'null'], 'description': 'Who can see it (public/merchant_public/merchant_invite/merchant_unlisted).'}, 'description': {'type': ['string', 'null'], 'description': 'Short description shown on the directory card.'}, 'merchant_id': {'type': ['string', 'null'], 'description': 'Owning merchant id. Null for a platform-wide directory.'}, 'cover_image_url': {'type': ['string', 'null'], 'description': 'Cover image URL.'}, 'has_content_page': {'type': ['boolean', 'null'], 'description': 'True when the directory has a custom Markdown page. Read the Markdown itself with catalogue-tag-get.'}, 'is_start_directory': {'type': ['boolean', 'null'], 'description': "True for the directory the merchant's catalogue opens on â\x80\x94 the root to navigate down from."}, 'mojito_language_code': {'type': ['string', 'null'], 'example': 'en', 'description': 'Directory language.'}, 'tags_interview_set_filter': {'type': ['array', 'null'], 'items': {'type': 'string'}, 'description': 'Tag filter selecting the coaching sessions this directory lists: a session appears when its own `tags` contain every tag here.'}}, 'additionalProperties': {}}, 'description': 'The catalogue directories for this page, ordered by id.'}, 'pagination': {'type': 'object', 'required': ['total', 'limit', 'offset', 'has_more'], 'properties': {'limit': {'type': ['integer', 'null'], 'example': 50, 'description': 'Page size used for this response.'}, 'total': {'type': ['integer', 'null'], 'example': 137, 'description': 'Total matching records across all pages.'}, 'offset': {'type': ['integer', 'null'], 'example': 0, 'description': 'Offset used for this response.'}, 'has_more': {'type': ['boolean', 'null'], 'example': True, 'description': 'True when more records exist beyond this page (offset + returned < total).'}}}, '_mcp_instructions': {'type': 'object', 'properties': {'conversation_id': {'type': 'string', 'description': 'The server-issued conversation identifier.'}}, 'description': 'Server-issued metadata for this conversation.'}}, 'x-fastmcp-top-level-schema': 'CatalogueTagListResponse'}
list_interview_results
List interview results
[Results] List the merchant's interview results. Rows carry the candidate's scores and recruiter risk flags, so this returns 20 at a time; page with `offset` while `pagination.has_more` is true, or narrow with `tab`/`interview_id`/`filter_text`. Paginated list of a merchant's interview results (the admin-portal results list), scoped to your token's merchant (or a merchant_id override). Capped at 1000 records per page.
只读 可访问外部资源 幂等
输入模式
{'type': 'object', 'required': [], 'properties': {'tab': {'enum': ['decided-rejected', 'undecided', 'shortlist', 'decided-selected', 'completed', 'incomplete', 'archived-interview', 'public_avatar', 'archived-public_avatar', ''], 'type': 'string', 'example': 'undecided', 'description': 'Filter by decision/completion state. Omit (or empty) to include all.'}, 'step': {'enum': ['pre-screening', 'interview', 'meeting'], 'type': 'string', 'example': 'interview', 'description': 'Filter by pipeline step type (pre-screening, interview or meeting). Omit for all.'}, 'type': {'enum': ['interview', 'coaching', 'assessment', 'public_avatar', 'persona', 'persona_interview'], 'type': 'string', 'default': 'interview', 'example': 'interview', 'description': 'Product type of results to list.'}, 'limit': {'type': 'integer', 'default': 20, 'example': 50, 'maximum': 1000.0, 'minimum': 1.0, 'description': 'Maximum number of records to return (1â\x80\x931000).'}, 'risks': {'type': 'string', 'description': 'Comma-separated list of recruiter-risk keys to filter by (matches any).'}, 'offset': {'type': 'integer', 'default': 0, 'example': 0, 'minimum': 0.0, 'description': 'Number of records to skip from the start of the result set.'}, 'order_by': {'enum': ['score', 'created_at_newest', 'created_at_oldest', 'updated_at_newest'], 'type': 'string', 'default': 'created_at_newest', 'example': 'created_at_newest', 'description': 'Sort order of the result set.'}, 'filter_text': {'type': 'string', 'description': 'Case-insensitive search on candidate name or email.'}, 'merchant_id': {'type': 'string', 'format': 'uuid', 'example': '28106cba-1c27-4e53-b149-32113e5e8e31', 'description': "Optional merchant to scope to. Admins and sub-merchant operators only; other callers always use their token's merchant."}, 'filter_emoji': {'type': 'string', 'description': 'Filter by the candidate emoji marker.'}, 'interview_id': {'type': 'string', 'format': 'uuid', 'description': 'Filter to a single interview definition id.'}, 'conversation_id': {'type': 'string', 'description': "Pass the exact conversation_id from the server's previous response, unchanged. The server provides it on the first call â\x80\x94 never invent one, and do not issue parallel tool calls until you have it. Keep passing the same conversation_id for the rest of the conversation, including after later user messages or on a different task; do not reset it when the user starts a new request."}, 'profile_interview_id': {'type': 'string', 'format': 'uuid', 'description': 'Filter to a single candidate (profile_interview) id.'}}}
输出模式
{'type': 'object', 'required': ['data', 'pagination'], 'properties': {'data': {'type': ['array', 'null'], 'items': {'type': 'object', 'required': ['id'], 'properties': {'id': {'type': ['string', 'null'], 'description': 'Position result row id.'}, 'type': {'type': ['string', 'null'], 'description': 'Product type.'}, 'emoji': {'type': ['string', 'null'], 'description': 'Emoji marker.'}, 'score': {'type': ['number', 'null'], 'description': 'Overall score.'}, 'status': {'type': ['string', 'null'], 'description': 'Row status.'}, 'is_test': {'type': ['boolean', 'null'], 'description': 'Whether a test result.'}, 'created_at': {'type': ['string', 'null'], 'description': 'Creation timestamp (ISO 8601).'}, 'profile_id': {'type': ['string', 'null'], 'description': 'Candidate profile id.'}, 'updated_at': {'type': ['string', 'null'], 'description': 'Last update timestamp (ISO 8601).'}, 'duration_ds': {'type': ['number', 'null'], 'description': 'Duration in deciseconds.'}, 'external_id': {'type': ['string', 'null'], 'description': 'External identifier.'}, 'merchant_id': {'type': ['string', 'null'], 'description': 'Owning merchant id.'}, 'coach_status': {'type': ['string', 'null'], 'description': 'Interview/coach status (started/completed/â\x80¦).'}, 'definition_id': {'type': ['string', 'null'], 'description': 'Interview definition id.'}, 'position_name': {'type': ['string', 'null'], 'description': 'Position / interview name.'}, 'position_step': {'type': ['string', 'null'], 'description': 'Pipeline step.'}, 'candidate_name': {'type': ['string', 'null'], 'description': 'Candidate name.'}, 'is_multi_stage': {'type': ['boolean', 'null'], 'description': 'Whether multi-stage.'}, 'candidate_email': {'type': ['string', 'null'], 'description': 'Candidate email.'}, 'decision_status': {'type': ['string', 'null'], 'description': 'Hiring decision (selected/rejected/â\x80¦).'}, 'recruiter_risks': {'description': 'Detected recruiter risk flags (jsonb).'}, 'score_answer_ai': {'type': ['number', 'null'], 'description': 'AI answer sub-score.'}, 'score_sentiment': {'type': ['number', 'null'], 'description': 'Sentiment sub-score.'}, 'processing_error': {'type': ['string', 'null'], 'description': 'Processing error, if any.'}, 'score_simulation': {'type': ['number', 'null'], 'description': 'Simulated overall score.'}, 'interview_started': {'type': ['boolean', 'null'], 'description': 'Whether the interview was started.'}, 'processing_status': {'type': ['string', 'null'], 'description': 'Processing status.'}, 'position_step_name': {'type': ['string', 'null'], 'description': 'Custom name of the position step, null when the step uses its default label.'}, 'score_interview_ai': {'type': ['number', 'null'], 'description': 'AI interview sub-score.'}, 'interview_result_id': {'type': ['string', 'null'], 'description': 'Interview result id (use with merchant-... detail endpoints).'}, 'position_step_count': {'type': ['number', 'null'], 'description': 'Number of steps in the position process.'}, 'position_step_index': {'type': ['number', 'null'], 'description': '1-based position of the step in the position process.'}, 'recruiter_shortlist': {'type': ['boolean', 'null'], 'description': 'Whether recruiter-shortlisted.'}, 'score_pronunciation': {'type': ['number', 'null'], 'description': 'Pronunciation sub-score.'}, 'mojito_language_code': {'type': ['string', 'null'], 'description': 'Platform language code.'}, 'position_def_step_id': {'type': ['string', 'null'], 'description': 'Position step definition id the row belongs to (null for single-stage interviews).'}, 'profile_interview_id': {'type': ['string', 'null'], 'description': 'Candidate (profile_interview) id.'}, 'kyc_processing_status': {'type': ['string', 'null'], 'description': 'KYC processing status.'}, 'score_words_per_minute': {'type': ['number', 'null'], 'description': 'Speaking-pace sub-score.'}, 'position_result_step_id': {'type': ['string', 'null'], 'description': 'Position result step id.'}, 'interview_result_pre_screening_id': {'type': ['string', 'null'], 'description': 'Pre-screening result id, if any.'}}, 'additionalProperties': {}}, 'description': "The merchant's interview results for this page."}, 'pagination': {'type': 'object', 'required': ['total', 'limit', 'offset', 'has_more'], 'properties': {'limit': {'type': ['integer', 'null'], 'example': 50, 'description': 'Page size used for this response.'}, 'total': {'type': ['integer', 'null'], 'example': 137, 'description': 'Total matching records across all pages.'}, 'offset': {'type': ['integer', 'null'], 'example': 0, 'description': 'Offset used for this response.'}, 'has_more': {'type': ['boolean', 'null'], 'example': True, 'description': 'True when more records exist beyond this page (offset + returned < total).'}}}, '_mcp_instructions': {'type': 'object', 'properties': {'conversation_id': {'type': 'string', 'description': 'The server-issued conversation identifier.'}}, 'description': 'Server-issued metadata for this conversation.'}}, 'x-fastmcp-top-level-schema': 'MerchantResultListResponse'}
list_interviews
List interviews
[Interviews] List the merchant's interview definitions. Paginated list of a merchant's interview definitions (the admin-portal interview list), scoped to your token's merchant (or a merchant_id override). Capped at 1000 records per page.
只读 可访问外部资源 幂等
输入模式
{'type': 'object', 'required': [], 'properties': {'type': {'enum': ['interview', 'coaching', 'assessment', 'public_avatar', 'persona', 'persona_interview'], 'type': 'string', 'default': 'interview', 'example': 'interview', 'description': 'Product type of interviews to list.'}, 'limit': {'type': 'integer', 'default': 50, 'example': 50, 'maximum': 1000.0, 'minimum': 1.0, 'description': 'Maximum number of records to return (1â\x80\x931000).'}, 'offset': {'type': 'integer', 'default': 0, 'example': 0, 'minimum': 0.0, 'description': 'Number of records to skip from the start of the result set.'}, 'status': {'enum': ['draft', 'active', 'archived', 'deleted', 'preparing', 'completed'], 'type': 'string', 'example': 'active', 'description': 'Filter by lifecycle status. Omit to include all statuses.'}, 'show_demo': {'enum': ['true', 'false'], 'type': 'string', 'default': 'false', 'example': 'false', 'description': 'Include demo/sample interviews.'}, 'filter_text': {'type': 'string', 'description': 'Case-insensitive search on the interview name.'}, 'merchant_id': {'type': 'string', 'format': 'uuid', 'example': '28106cba-1c27-4e53-b149-32113e5e8e31', 'description': "Optional merchant to scope to. Admins and sub-merchant operators only; other callers always use their token's merchant."}, 'show_public': {'enum': ['true', 'false'], 'type': 'string', 'default': 'false', 'example': 'false', 'description': 'Include interviews shared publicly across merchants (coaching/avatars).'}, 'filter_emoji': {'type': 'string', 'description': 'Filter by the interview emoji marker.'}, 'conversation_id': {'type': 'string', 'description': "Pass the exact conversation_id from the server's previous response, unchanged. The server provides it on the first call â\x80\x94 never invent one, and do not issue parallel tool calls until you have it. Keep passing the same conversation_id for the rest of the conversation, including after later user messages or on a different task; do not reset it when the user starts a new request."}}}
输出模式
{'type': 'object', 'required': ['data', 'pagination'], 'properties': {'data': {'type': ['array', 'null'], 'items': {'type': 'object', 'required': ['id'], 'properties': {'id': {'type': ['string', 'null'], 'description': 'Interview definition id.'}, 'name': {'type': ['string', 'null'], 'description': 'Interview name.'}, 'type': {'type': ['string', 'null'], 'description': 'Product type (interview/coaching/â\x80¦).'}, 'emoji': {'type': ['string', 'null'], 'description': 'Emoji marker.'}, 'is_ats': {'type': ['boolean', 'null'], 'description': 'Whether the interview is ATS-integrated.'}, 'status': {'type': ['string', 'null'], 'description': 'Lifecycle status.'}, 'recording': {'type': ['string', 'null'], 'description': 'Per-answer recording/proctoring mode.'}, 'created_at': {'type': ['string', 'null'], 'description': 'Creation timestamp (ISO 8601).'}, 'updated_at': {'type': ['string', 'null'], 'description': 'Last update timestamp (ISO 8601).'}, 'visibility': {'type': ['string', 'null'], 'description': 'Visibility (merchant_public/invite/unlisted/â\x80¦).'}, 'environment': {'type': ['string', 'null'], 'description': 'Environment (production/test/â\x80¦).'}, 'merchant_id': {'type': ['string', 'null'], 'description': 'Owning merchant id.'}, 'type_avatar': {'type': ['string', 'null'], 'description': 'Avatar type used by the interview.'}, 'calc_duration': {'type': ['number', 'null'], 'description': 'Calculated duration.'}, 'interview_last': {'type': ['string', 'null'], 'description': 'Timestamp of the most recent interview (ISO 8601).'}, 'is_multi_stage': {'type': ['boolean', 'null'], 'description': 'Whether the interview is multi-stage.'}, 'cover_image_url': {'type': ['string', 'null'], 'description': 'Cover image URL.'}, 'interview_count': {'type': ['number', 'null'], 'description': 'Number of interviews run against this definition.'}, 'mojito_language_code': {'type': ['string', 'null'], 'description': 'Platform language code.'}, 'speech_language_code': {'type': ['string', 'null'], 'description': 'Speech language code.'}, 'recording_full_session': {'type': ['string', 'null'], 'description': 'Full-session recording mode.'}, 'billing_single_position': {'type': ['boolean', 'null'], 'description': 'Single-position billing flag.'}, 'billing_single_position_end_at': {'type': ['string', 'null'], 'description': 'Single-position billing end (ISO 8601).'}}, 'additionalProperties': {}}, 'description': "The merchant's interview definitions for this page, newest-updated first."}, 'pagination': {'type': 'object', 'required': ['total', 'limit', 'offset', 'has_more'], 'properties': {'limit': {'type': ['integer', 'null'], 'example': 50, 'description': 'Page size used for this response.'}, 'total': {'type': ['integer', 'null'], 'example': 137, 'description': 'Total matching records across all pages.'}, 'offset': {'type': ['integer', 'null'], 'example': 0, 'description': 'Offset used for this response.'}, 'has_more': {'type': ['boolean', 'null'], 'example': True, 'description': 'True when more records exist beyond this page (offset + returned < total).'}}}, '_mcp_instructions': {'type': 'object', 'properties': {'conversation_id': {'type': 'string', 'description': 'The server-issued conversation identifier.'}}, 'description': 'Server-issued metadata for this conversation.'}}, 'x-fastmcp-top-level-schema': 'MerchantInterviewListResponse'}
list_languages
List supported languages
[Admin] List supported platform (mojito) languages: the `code` to pass as `mojito_language_code`, English/local names, SVG flag URL, per-interface enablement flags, and Azure speech accents. Returns all supported platform (mojito) languages: the mojito language code, English and local names, and an SVG flag image URL. Use the `code` as `mojito_language_code` when creating interviews or personas.
只读 可访问外部资源 幂等
输入模式
{'type': 'object', 'required': [], 'properties': {'conversation_id': {'type': 'string', 'description': "Pass the exact conversation_id from the server's previous response, unchanged. The server provides it on the first call â\x80\x94 never invent one, and do not issue parallel tool calls until you have it. Keep passing the same conversation_id for the rest of the conversation, including after later user messages or on a different task; do not reset it when the user starts a new request."}}}
输出模式
{'type': 'object', 'required': ['languages'], 'properties': {'languages': {'type': ['array', 'null'], 'items': {'type': 'object', 'required': ['code', 'name_english', 'name_local', 'flag_image', 'flag_emoji', 'flag_unicode', 'coaching_interface', 'interview_interface', 'admin_interface', 'accents'], 'properties': {'code': {'type': ['string', 'null'], 'example': 'en', 'description': 'Mojito platform language code. Pass this as `mojito_language_code` when creating interviews / personas.'}, 'accents': {'type': ['array', 'null'], 'items': {'type': 'object', 'required': ['code', 'name'], 'properties': {'code': {'type': ['string', 'null'], 'example': 'en-US', 'description': 'Azure speech locale code for the accent/regional variant.'}, 'name': {'type': ['string', 'null'], 'example': 'English (United States)', 'description': 'Human-readable accent name.'}}}, 'description': 'Azure speech regional accents / variants available for this language, each with its locale `code` and `name`.'}, 'flag_emoji': {'type': ['string', 'null'], 'example': 'ð\x9f\x87ºð\x9f\x87¸', 'description': 'Flag emoji for the language.'}, 'flag_image': {'type': ['string', 'null'], 'example': 'https://cdn.jsdelivr.net/npm/country-flag-emoji-json@2.0.0/dist/images/US.svg', 'description': 'URL to an SVG flag image for the language (same source the app UI renders).'}, 'name_local': {'type': ['string', 'null'], 'example': 'English', 'description': 'Language name written in the language itself.'}, 'flag_unicode': {'type': ['string', 'null'], 'example': 'U+1F1FA U+1F1F8', 'description': 'Unicode code points for the flag emoji.'}, 'name_english': {'type': ['string', 'null'], 'example': 'English', 'description': 'Language name in English.'}, 'admin_interface': {'type': ['boolean', 'null'], 'example': True, 'description': 'Whether this language is enabled on the admin interface.'}, 'coaching_interface': {'type': ['boolean', 'null'], 'example': True, 'description': 'Whether this language is enabled on the coaching (consumer) interface.'}, 'interview_interface': {'type': ['boolean', 'null'], 'example': True, 'description': 'Whether this language is enabled on the interview interface.'}}}, 'description': 'Supported platform languages, sorted by English name.'}, '_mcp_instructions': {'type': 'object', 'properties': {'conversation_id': {'type': 'string', 'description': 'The server-issued conversation identifier.'}}, 'description': 'Server-issued metadata for this conversation.'}}, 'x-fastmcp-top-level-schema': 'PlatformLanguagesListResponse'}
list_my_merchants
List merchants you can act as
FALLBACK merchant list for clients WITHOUT UI support. Do NOT use this to choose or switch merchants when a UI is available — call `jobmojito_configuration` instead (it renders an interactive picker), and do not hand-format a merchant list as text. Use this tool only when the client cannot render MCP App UI. Returns the user's own account plus any sub-merchants; after a pick, pass `merchant_id=<chosen id>` on subsequent calls (OMIT for the own account).
只读 幂等
输入模式
{'type': 'object', 'properties': {'search': {'type': 'string', 'default': '', 'description': 'Optional case-insensitive filter on sub-merchant name.'}, 'conversation_id': {'type': 'string', 'description': "Pass the exact conversation_id from the server's previous response, unchanged. The server provides it on the first call â\x80\x94 never invent one, and do not issue parallel tool calls until you have it. Keep passing the same conversation_id for the rest of the conversation, including after later user messages or on a different task; do not reset it when the user starts a new request."}}, 'additionalProperties': False}
输出模式
{'type': 'object', 'properties': {'_mcp_instructions': {'type': 'object', 'properties': {'conversation_id': {'type': 'string', 'description': 'The server-issued conversation identifier.'}}, 'description': 'Server-issued metadata for this conversation.'}}, 'additionalProperties': True}
list_sub_merchants
List sub-merchants
[Admin] List sub-merchants under the merchant account. Paginated list of the sub-merchants the caller administers (the admin-portal sub-merchants list). Visibility is enforced by row-level security. Capped at 1000 records per page.
只读 可访问外部资源 幂等
输入模式
{'type': 'object', 'required': [], 'properties': {'limit': {'type': 'integer', 'default': 50, 'example': 50, 'maximum': 1000.0, 'minimum': 1.0, 'description': 'Maximum number of records to return (1â\x80\x931000).'}, 'offset': {'type': 'integer', 'default': 0, 'example': 0, 'minimum': 0.0, 'description': 'Number of records to skip from the start of the result set.'}, 'order_by': {'enum': ['name', 'created_at_newest', 'created_at_oldest'], 'type': 'string', 'default': 'created_at_newest', 'example': 'created_at_newest', 'description': 'Sort order of the result set.'}, 'filter_text': {'type': 'string', 'description': 'Case-insensitive search on the sub-merchant name.'}, 'merchant_id': {'type': 'string', 'format': 'uuid', 'example': '28106cba-1c27-4e53-b149-32113e5e8e31', 'description': "Optional merchant to scope to. Admins and sub-merchant operators only; other callers always use their token's merchant."}, 'conversation_id': {'type': 'string', 'description': "Pass the exact conversation_id from the server's previous response, unchanged. The server provides it on the first call â\x80\x94 never invent one, and do not issue parallel tool calls until you have it. Keep passing the same conversation_id for the rest of the conversation, including after later user messages or on a different task; do not reset it when the user starts a new request."}}}
输出模式
{'type': 'object', 'required': ['data', 'pagination'], 'properties': {'data': {'type': ['array', 'null'], 'items': {'type': 'object', 'required': ['id'], 'properties': {'id': {'type': ['string', 'null'], 'description': 'Sub-merchant id.'}, 'name': {'type': ['string', 'null'], 'description': 'Sub-merchant name.'}, 'users': {'description': 'Users linked to this sub-merchant (jsonb).'}, 'status': {'type': ['string', 'null'], 'description': 'Status.'}, 'created_at': {'type': ['string', 'null'], 'description': 'Creation timestamp (ISO 8601).'}, 'info_notes': {'type': ['string', 'null'], 'description': 'Internal notes.'}, 'business_type': {'type': ['string', 'null'], 'description': 'Business type.'}, 'contact_email': {'type': ['string', 'null'], 'description': 'Primary contact email.'}, 'admin_profiles': {'description': 'Admin profiles linked to this sub-merchant (jsonb).'}, 'contact_person': {'type': ['string', 'null'], 'description': 'Primary contact name.'}, 'image_logo_url': {'type': ['string', 'null'], 'description': 'Logo image URL.'}, 'billing_country': {'type': ['string', 'null'], 'description': 'Billing country.'}, 'frontend_domain': {'type': ['string', 'null'], 'description': 'Consumer frontend domain.'}, 'interview_count': {'type': ['number', 'null'], 'description': 'Total interviews run.'}, 'register_domain': {'type': ['string', 'null'], 'description': 'Registration domain.'}, 'credits_used_30d': {'type': ['number', 'null'], 'description': 'Credits used in the last 30 days.'}, 'interview_latest': {'type': ['string', 'null'], 'description': 'Most recent interview timestamp (ISO 8601).'}, 'merchant_features': {'description': 'Enabled feature flags (jsonb).'}, 'credits_used_total': {'type': ['number', 'null'], 'description': 'Total credits used.'}, 'consumer_webanalytics': {'type': ['string', 'null'], 'description': 'Consumer web-analytics id.'}, 'interview_webanalytics': {'type': ['string', 'null'], 'description': 'Interview web-analytics id.'}, 'interview_frontend_domain': {'type': ['string', 'null'], 'description': 'Interview frontend domain.'}, 'interview_subscription_type': {'type': ['string', 'null'], 'description': 'Interview subscription type.'}, 'interview_subscription_status': {'type': ['string', 'null'], 'description': 'Interview subscription status.'}, 'stripe_interview_subscription_start': {'type': ['string', 'null'], 'description': 'Subscription start (ISO 8601).'}}, 'additionalProperties': {}}, 'description': 'The sub-merchants the caller administers for this page.'}, 'pagination': {'type': 'object', 'required': ['total', 'limit', 'offset', 'has_more'], 'properties': {'limit': {'type': ['integer', 'null'], 'example': 50, 'description': 'Page size used for this response.'}, 'total': {'type': ['integer', 'null'], 'example': 137, 'description': 'Total matching records across all pages.'}, 'offset': {'type': ['integer', 'null'], 'example': 0, 'description': 'Offset used for this response.'}, 'has_more': {'type': ['boolean', 'null'], 'example': True, 'description': 'True when more records exist beyond this page (offset + returned < total).'}}}, '_mcp_instructions': {'type': 'object', 'properties': {'conversation_id': {'type': 'string', 'description': 'The server-issued conversation identifier.'}}, 'description': 'Server-issued metadata for this conversation.'}}, 'x-fastmcp-top-level-schema': 'MerchantSubMerchantListResponse'}
register_users_for_interview
Register candidates for interview
[Interviews] Register users/candidates for a specific interview and return their personal interview links. Registers (or updates) one or more candidate profiles for an interview and returns a one-time interview URL for each. Accepts a Supabase user JWT (merchant/admin) or the service key (merchant_id then required).
可能执行破坏性操作 可访问外部资源
输入模式
{'type': 'object', 'required': ['users', 'interview_id'], 'properties': {'users': {'type': ['array', 'null'], 'items': {'type': 'object', 'properties': {'name': {'type': ['string', 'null'], 'example': 'Peter Parker', 'description': 'Display name of the candidate.'}, 'email': {'type': ['string', 'null'], 'example': 'peter.parker@example.com', 'description': 'Email used to identify and invite the candidate. Validated per item, not request-level.'}, 'phone': {'type': ['string', 'null'], 'example': '+421903123456', 'description': 'Optional mobile number in international format (E.164, e.g. +421903123456). Enables SMS / WhatsApp invitation and reminder notifications when the interview has candidate_notification_channel set. Never overwrites a phone already stored on the candidate.'}, 'external_id': {'type': ['string', 'null'], 'example': 'abcd', 'description': 'Optional caller-supplied id, stored on the candidate profile.'}}}, 'example': [{'name': 'Peter Parker', 'email': 'peter.parker@example.com', 'external_id': 'abcd'}, {'name': 'Mary Jane Watson', 'email': 'mary.jane@example.com'}], 'description': 'Candidates to register for the interview. Each gets a one-time interview URL.'}, 'is_test': {'anyOf': [{'type': 'boolean'}, {'type': 'string'}, {}], 'description': 'When true (or the string "true"), mints a test token that can take a draft/unpublished interview and flags the result as a test. For a DRAFT interview it also recompiles the definition (interview_recalc_definition) first, so the test session includes the current questions/welcome. This makes it a single-call "trigger interview test".'}, 'hide_menu': {'anyOf': [{'type': 'boolean'}, {'type': 'string'}, {}], 'description': 'When true (or the string "true"), the interview UI hides its menu (view_hm).'}, 'send_email': {'type': ['boolean', 'null'], 'description': 'Whether to send an invitation email to each registered candidate.'}, 'hide_iframe': {'anyOf': [{'type': 'boolean'}, {'type': 'string'}, {}], 'description': 'When true (or the string "true"), the interview UI hides its iframe chrome (view_hi).'}, 'merchant_id': {'type': ['string', 'null'], 'format': 'uuid', 'example': 'b5201178-46dd-4a20-a1af-7ffd647f834b', 'description': 'Merchant id. Required when authenticating with the service key; for user tokens it is optional and only honored for admin / sub-merchant accounts.'}, 'interview_id': {'type': ['string', 'null'], 'format': 'uuid', 'example': '04e09fa5-3fb8-4236-b37d-fca2bcd1cb66', 'minLength': 1, 'description': 'Interview definition (interview_def_set) or position (position_def_set) id to register users for.'}, 'conversation_id': {'type': 'string', 'description': "Pass the exact conversation_id from the server's previous response, unchanged. The server provides it on the first call â\x80\x94 never invent one, and do not issue parallel tool calls until you have it. Keep passing the same conversation_id for the rest of the conversation, including after later user messages or on a different task; do not reset it when the user starts a new request."}}}
输出模式
{'type': 'object', 'required': ['result'], 'properties': {'result': {'type': 'array', 'items': {'type': 'object', 'properties': {'name': {'type': ['string', 'null']}, 'email': {'type': ['string', 'null']}, 'phone': {'type': ['string', 'null']}, 'result': {'type': ['string', 'null'], 'example': 'ok', 'description': '"ok" on success, otherwise an "Error: ..." message for that user.'}, 'external_id': {'type': ['string', 'null']}, 'interview_url': {'type': ['string', 'null'], 'description': 'One-time interview URL containing the minted interview_token. Present only on success.'}}, 'additionalProperties': {}}, 'description': 'The input users, each annotated with its registration result and (on success) interview URL.', 'x-fastmcp-top-level-schema': 'JobInterviewRegisterUsersResponse'}, '_mcp_instructions': {'type': 'object', 'properties': {'conversation_id': {'type': 'string', 'description': 'The server-issued conversation identifier.'}}, 'description': 'Server-issued metadata for this conversation.'}}, 'x-fastmcp-wrap-result': True}
request_another_interview_attempt
Re-open interview for another attempt
[Results] Re-open a submitted interview result so the candidate can retry. Marks a submitted (active + completed) interview result as unsuccessful so the candidate can retake it. Resets the result to draft and clears the recruiter decision.
可能执行破坏性操作 可访问外部资源
输入模式
{'type': 'object', 'required': ['interview_result_id'], 'properties': {'conversation_id': {'type': 'string', 'description': "Pass the exact conversation_id from the server's previous response, unchanged. The server provides it on the first call â\x80\x94 never invent one, and do not issue parallel tool calls until you have it. Keep passing the same conversation_id for the rest of the conversation, including after later user messages or on a different task; do not reset it when the user starts a new request."}, 'interview_result_id': {'type': ['string', 'null'], 'format': 'uuid', 'example': '93c98d21-e04d-4a84-9afa-ed154cf73636', 'minLength': 1, 'description': 'The interview result to reopen for another attempt.'}}}
输出模式
{'type': 'object', 'properties': {'_mcp_instructions': {'type': 'object', 'properties': {'conversation_id': {'type': 'string', 'description': 'The server-issued conversation identifier.'}}, 'description': 'Server-issued metadata for this conversation.'}}, 'description': 'Empty object on success.', 'x-fastmcp-top-level-schema': 'RequestAnotherAttemptResponse'}
search_documentation
Search JobMojito documentation
Search ALL JobMojito documentation. This is the single entry point. One call searches both documentation sources in parallel and returns a merged, source-labeled list — you do not need to choose a source or call a separate tool: • "developer" — developer.jobmojito.com: API reference, request/response schemas, tables, webhooks, code examples, integration guides. • "help" — help.jobmojito.com: recruiter, candidate, and administrator product guides (how the platform behaves for end users). Use this whenever you need to understand how a feature, endpoint, field, or workflow works — including before calling an action tool you're unsure about. Then call `get_documentation(url)` with a returned URL to read the full page.
只读 可访问外部资源 幂等
输入模式
{'type': 'object', 'required': ['query'], 'properties': {'limit': {'type': 'integer', 'default': 8, 'description': 'Max results per source (1-25).'}, 'query': {'type': 'string', 'description': 'Natural-language search query or keywords.'}, 'source': {'type': 'string', 'default': 'all', 'description': '"all" (default), "developer", or "help" to restrict the search.'}, 'conversation_id': {'type': 'string', 'description': "Pass the exact conversation_id from the server's previous response, unchanged. The server provides it on the first call â\x80\x94 never invent one, and do not issue parallel tool calls until you have it. Keep passing the same conversation_id for the rest of the conversation, including after later user messages or on a different task; do not reset it when the user starts a new request."}}, 'additionalProperties': False}
输出模式
{'type': 'object', 'properties': {'_mcp_instructions': {'type': 'object', 'properties': {'conversation_id': {'type': 'string', 'description': 'The server-issued conversation identifier.'}}, 'description': 'Server-issued metadata for this conversation.'}}, 'additionalProperties': True}
set_interview_state
Change interview state
[Interviews] Change the state of an interview/position (e.g. open, closed). Changes the lifecycle status of an interview or position (draft, active, archived, preparing, completed, deleted) and/or manages its embed key. Provide at least one of `status` or `is_embedded`.
可能执行破坏性操作 可访问外部资源 幂等
输入模式
{'type': 'object', 'required': ['position_id'], 'properties': {'status': {'enum': ['draft', 'active', 'archived', 'deleted', 'preparing', 'completed', None], 'type': ['string', 'null'], 'description': 'New lifecycle status to apply.'}, 'is_embedded': {'type': ['boolean', 'null'], 'description': 'Controls iframe embedding of the interview on an external page. When true, ensures an embed key exists (returns embed_id/embed_signing_key, used to authenticate/sign the iframe embed). When false, removes the embed keys (disables embedding).'}, 'position_id': {'type': ['string', 'null'], 'format': 'uuid', 'example': '00000000-0000-0000-0000-000000000000', 'minLength': 1, 'description': 'Interview definition id or position id whose state should change.'}, 'conversation_id': {'type': 'string', 'description': "Pass the exact conversation_id from the server's previous response, unchanged. The server provides it on the first call â\x80\x94 never invent one, and do not issue parallel tool calls until you have it. Keep passing the same conversation_id for the rest of the conversation, including after later user messages or on a different task; do not reset it when the user starts a new request."}}}
输出模式
{'type': 'object', 'required': ['result'], 'properties': {'result': {'anyOf': [{'type': 'object', 'required': ['success'], 'properties': {'success': {'type': ['boolean', 'null']}}}, {'type': 'object', 'required': ['embed_id', 'embed_signing_key'], 'properties': {'embed_id': {'type': ['string', 'null']}, 'embed_signing_key': {'type': ['string', 'null']}}}], 'description': 'Returns `{ embed_id, embed_signing_key }` when an embed key was created/returned (is_embedded=true), otherwise `{ success: true }`.', 'x-fastmcp-top-level-schema': 'JobInterviewSetStateResponse'}, '_mcp_instructions': {'type': 'object', 'properties': {'conversation_id': {'type': 'string', 'description': 'The server-issued conversation identifier.'}}, 'description': 'Server-issued metadata for this conversation.'}}, 'x-fastmcp-wrap-result': True}
update_catalogue_directory
Update coaching catalogue directory
[Coaching catalogue] Update a coaching catalogue directory: rename it, change which sessions it lists (`tags_interview_set_filter`), re-order its sub-directories (`tags_sub`), or author its custom Markdown page (`content_md`). Only the fields you send are changed. Coaching-platform feature. Updates a directory (page) of the coaching portal catalogue. Only the fields present in the request body are written — everything else keeps its current value, and sending null clears a nullable field. Use it to rename a directory, re-point which sessions it lists (`tags_interview_set_filter`), re-order or replace its sub-directories (`tags_sub`), or author its custom Markdown page (`content_md`).
可能执行破坏性操作 可访问外部资源 幂等
输入模式
{'type': 'object', 'required': ['id'], 'properties': {'id': {'type': ['string', 'null'], 'example': 'sales-coaching-en', 'pattern': '^[a-z0-9]+(?:(?:-|_)+[a-z0-9]+)*$', 'minLength': 1, 'description': 'Id of the directory to update (the catalogue URL segment). The id itself cannot be changed â\x80\x94 create a new directory instead.'}, 'name': {'type': ['string', 'null'], 'example': 'Sales coaching', 'minLength': 1, 'description': 'Display name of the directory.'}, 'status': {'enum': ['draft', 'active', 'archived', None], 'type': ['string', 'null'], 'example': 'active', 'description': 'Lifecycle status of the catalogue directory. Options â\x80\x94 `draft`: Not published â\x80\x94 the directory exists but is not served to visitors. | `active`: Published and served in the catalogue. | `archived`: Retired â\x80\x94 kept for reference but no longer served..'}, 'tags_sub': {'type': ['array', 'null'], 'items': {'type': 'string'}, 'example': ['sales-coaching-objections-en', 'sales-coaching-closing-en'], 'description': 'Ids of the directories nested under this one, in display order. Replaces the whole list â\x80\x94 send the full set, not just the additions. A referenced directory only appears if it exists and is visible to the viewer.'}, 'coach_plan': {'enum': ['demo', 'screening', '2nd', '3rd', 'closing', 'job-specific', 'other', None], 'type': ['string', 'null'], 'example': 'screening', 'description': 'Coaching-plan stage this item belongs to, used by the coaching-plan progress view. Omit/null to leave it out of any plan. Options â\x80\x94 `demo`: Demo session. | `screening`: Screening-interview practice. | `2nd`: Second-interview practice. | `3rd`: Third-interview practice. | `closing`: Closing / salary-negotiation practice. | `job-specific`: Job-specific coaching. | `other`: Anything that does not fit the other buckets..'}, 'content_md': {'type': ['string', 'null'], 'example': '## Sales coaching\n\nPick a session to practise with.\n\n[chip:6 sessions] [chip:Beginner,tone=accent]\n\n[sessions:filter=objection-handling,limit=6]\n', 'description': 'Markdown for the custom directory page. Sending null removes the custom page and restores the default grid; sending a string replaces the whole page. Directives, each ALONE on its own line: `[plan-progress]`, `[directory:<tag-id>]`, `[session:<interview-id>]`, `[sessions]`, `[sessions:<term>]`, `[sessions:filter=<term>,limit=<n>]`. Chips, callouts, cards, columns and buttons are available too â\x80\x94 formatting guide: https://developer.jobmojito.com/cookbooks/format-content-with-markdown'}, 'visibility': {'enum': ['public', 'merchant_public', 'merchant_invite', 'merchant_unlisted', None], 'type': ['string', 'null'], 'example': 'merchant_public', 'description': "Who can see the catalogue directory. Options â\x80\x94 `public`: Shared across every merchant. Platform admins only â\x80\x94 a merchant caller is rejected by row-level security. | `merchant_public`: Listed in the merchant's own catalogue â\x80\x94 the normal choice. | `merchant_invite`: Owned by the merchant but not listed; reachable only for invited users. | `merchant_unlisted`: Owned by the merchant but not listed; reachable only via a direct link.."}, 'description': {'type': ['string', 'null'], 'description': 'Short description shown on the directory card.'}, 'conversation_id': {'type': 'string', 'description': "Pass the exact conversation_id from the server's previous response, unchanged. The server provides it on the first call â\x80\x94 never invent one, and do not issue parallel tool calls until you have it. Keep passing the same conversation_id for the rest of the conversation, including after later user messages or on a different task; do not reset it when the user starts a new request."}, 'cover_image_url': {'type': ['string', 'null'], 'description': 'Cover image URL shown on the directory card. null clears it.'}, 'mojito_language_code': {'enum': ['ar', 'bg', 'zh', 'hr', 'cs', 'da', 'nl', 'en', 'fil', 'fi', 'fr', 'de', 'el', 'hi', 'hu', 'id', 'it', 'ja', 'ko', 'ms', 'no', 'pl', 'pt', 'br', 'ro', 'ru', 'sk', 'es', 'sv', 'ta', 'th', 'tr', 'uk', 'vi', None], 'type': ['string', 'null'], 'example': 'en', 'description': 'Language of the directory (one of the platform-languages.json codes). The catalogue groups directories by language.'}, 'tags_interview_set_filter': {'type': ['array', 'null'], 'items': {'type': 'string'}, 'example': ['sales', 'objection-handling'], 'description': 'Tag filter selecting which coaching sessions this directory lists: a session appears when its own `tags` contain EVERY tag here (an AND, not an OR). Only `active` coaching/persona sessions with visibility `public` or `merchant_public` are listed. Set the matching tags on the session with the create-interview / job-interview-update `tags` field.'}}}
输出模式
{'type': 'object', 'required': ['id', 'updated_fields', 'catalogue_url'], 'properties': {'id': {'type': ['string', 'null'], 'example': 'sales-coaching-en', 'description': 'Id of the updated directory.'}, 'catalogue_url': {'type': ['string', 'null'], 'example': 'https://coaching.example.com/catalogue/sales-coaching-en', 'description': 'Public URL of the directory page, when the merchant has a coaching-portal domain configured. Null otherwise.'}, 'updated_fields': {'type': ['array', 'null'], 'items': {'type': 'string'}, 'example': ['content_md', 'tags_interview_set_filter'], 'description': 'Names of the fields that were written.'}, '_mcp_instructions': {'type': 'object', 'properties': {'conversation_id': {'type': 'string', 'description': 'The server-issued conversation identifier.'}}, 'description': 'Server-issued metadata for this conversation.'}}, 'description': 'Confirmation of what was updated.', 'x-fastmcp-top-level-schema': 'CatalogueTagUpdateResponse'}
update_interview
Update interview or position
[Interviews] Update the configuration of an existing interview/position: name, description, avatar template, recording, scoring, tags and the rest of the create-time settings. Only the fields you send are changed. To change the questions, send `questions` — the WHOLE list you want the interview to end up with, in order, in the format get_interview_definition returns. OMIT `questions` and the existing questions are left completely alone; there is no way to change one question on its own, so read the interview first, edit that array, and send it back. Resending an unchanged array does nothing. Not updated by this tool at all: the welcome and thank-you messages and the instructional-video screen (stored as steps, not questions), and the language, which the existing questions are already written in. Use `tags` to place a coaching session into a catalogue directory. MULTI-STAGE POSITIONS: some per-interview settings do not exist at position level and are rejected with a 422 naming the field — `candidate_expectations_json` is the one seen in practice. Read the position with get_interview_definition, then update the individual stage you mean instead of sending that field to the position. Updates the configuration of an existing interview (single-stage) or position (multi-stage). Only the fields present in the request body are written — everything else keeps its current value, and sending null clears a nullable field. The question list is only touched when you send `questions`; omit that field and the questions are left exactly as they are. When sent, it must be the complete list and is applied as a diff against what is stored (matched on external_id, then id, then identical content), so unchanged questions keep their existing records, edited ones are unlinked and re-created, and dropped ones are unlinked — and re-sending the array job-interview-get returned changes nothing. See the field description, and `questions_diff` in the response for what was decided. Questions of an interview that is already `active` can only be changed on interactive avatar templates, where re-publishing is instant; on the offline (pre-rendered video) templates set the interview back to `draft` first. The welcome / thank-you messages and the instructional-video screen are stored as steps rather than questions and are never changed here. `mojito_language_code` cannot be changed — the existing questions and rendered videos are in the original language — so create a new interview to change language. A multi-stage position only carries the shared identity fields (name, code, location, description, description_long, cover_image_url, department, salary, available_till, recruiter, status, visibility, hiring_for_company); sending an interview-only field for a position is a 422.
可能执行破坏性操作 可访问外部资源 幂等
输入模式
{'type': 'object', 'required': ['position_id'], 'properties': {'code': {'type': ['string', 'null'], 'description': 'External code/reference. Blank is stored as null.'}, 'name': {'type': ['string', 'null'], 'example': 'Project manager', 'description': 'Interview / position name.'}, 'tags': {'type': ['array', 'null'], 'items': {'type': 'string'}, 'example': ['interview-practice', 'sales'], 'description': "Free-form tags stored on the interview. Tags are also the coaching-catalogue mapping key: a catalogue directory (see the catalogue-tag-create / catalogue-tag-update endpoints) lists a coaching or persona session when the session's tags contain EVERY tag in that directory's `tags_interview_set_filter`. Only `active` sessions with visibility `public` or `merchant_public` are listed."}, 'type': {'enum': ['interview', 'coaching', 'assessment', None], 'type': ['string', 'null'], 'example': 'interview', 'description': 'Product type of the interview. Changing it also re-derives `type_credit` (null for interview/assessment, otherwise interview_coach_manager) unless you send `type_credit` explicitly. Single-stage interviews only.'}, 'status': {'enum': ['draft', 'active', 'archived', 'deleted', 'preparing', 'completed', None], 'type': ['string', 'null'], 'example': 'active', 'description': 'New lifecycle status. Applied through the same interview_set_status routine as job-interview-set-state (which is also where you manage the iframe embed key).'}, 'location': {'type': ['string', 'null'], 'example': 'remote', 'description': 'Interview location (column `interview_location`). Blank is stored as null.'}, 'questions': {'type': ['array', 'null'], 'items': {'type': 'object', 'required': ['question'], 'properties': {'id': {'type': ['string', 'null'], 'description': "Identifier for this question. job-interview-get returns the question's real id here; send it back to job-interview-update so an unchanged question keeps its existing record (and with it its answer rules and any rendered avatar video). Also the handle another question references via conditional_question_main_id. On job-interview-create-from-array it is a caller-local value, only needed for those references."}, 'label': {'type': ['string', 'null'], 'description': 'Optional label/tag stored on the question.'}, 'duration': {'type': ['number', 'null'], 'description': 'Answer duration in seconds for this question.'}, 'question': {'type': ['string', 'null'], 'description': 'The question text shown to the candidate.'}, 'is_expert': {'type': ['boolean', 'null'], 'description': "Expert listening question (view 'with listening expert')."}, 'external_id': {'type': ['string', 'null'], 'description': 'External identifier stored on the question. job-interview-update matches on this first, so an ATS that owns stable ids can send its own array and have the diff line up without round-tripping our ids.'}, 'external_data': {'type': ['object', 'null'], 'description': 'Arbitrary JSON metadata stored on the question.', 'additionalProperties': {}}, 'is_conditional': {'type': ['boolean', 'null'], 'description': "Conditional follow-up question (view 'with listening conditional'). Use with conditional_question_main_id."}, 'knowledge_base_id': {'type': ['string', 'null'], 'description': 'Knowledge-base store id (uuid) the question draws context from.'}, 'is_multiple_choice': {'type': ['boolean', 'null'], 'description': "Multiple-choice question (view 'multiple choice')."}, 'is_without_scoring': {'type': ['boolean', 'null'], 'description': "Question is asked but not scored (view 'without scoring')."}, 'mojito_language_code': {'enum': ['ar', 'bg', 'zh', 'hr', 'cs', 'da', 'nl', 'en', 'fil', 'fi', 'fr', 'de', 'el', 'hi', 'hu', 'id', 'it', 'ja', 'ko', 'ms', 'no', 'pl', 'pt', 'br', 'ro', 'ru', 'sk', 'es', 'sv', 'ta', 'th', 'tr', 'uk', 'vi', None], 'type': ['string', 'null'], 'example': 'en', 'description': 'Per-question language override (one of the platform-languages.json codes). Inherits the interview language when omitted.'}, 'question_alternatives': {'type': ['array', 'null'], 'items': {'type': 'string'}, 'description': 'Alternative phrasings for the question.'}, 'candidate_expectations_json': {'type': ['object', 'null'], 'properties': {'weak': {'type': ['array', 'null'], 'items': {'type': 'string'}, 'description': 'Baseline requirements every viable candidate should meet (table stakes).'}, 'strong': {'type': ['array', 'null'], 'items': {'type': 'string'}, 'description': 'High-bar requirements only standout candidates clear.'}, 'moderate': {'type': ['array', 'null'], 'items': {'type': 'string'}, 'description': 'Requirements expected of a solid, competent candidate.'}}, 'description': 'Per-question candidate expectations, bucketed by requirement level (weak/moderate/strong). Extra keys are preserved.'}, 'conditional_question_main_id': {'type': ['string', 'null'], 'description': 'For a conditional question, the id (the "id" field above) of the parent question in this same array that triggers it. The parent must appear earlier in the array than the conditional question referencing it.'}, 'is_candidate_asking_recruiter': {'type': ['boolean', 'null'], 'description': "Candidate-asks-recruiter prompt (view 'candidate asking recruiter')."}}, 'additionalProperties': {}}, 'minItems': 1, 'description': "OPTIONAL. Omit this field entirely and the interview's questions are left exactly as they are â\x80\x94 this endpoint only touches questions when you send the array. When you do send it, send the COMPLETE list you want the interview to end up with, in order, in the same format job-interview-create-from-array accepts and job-interview-get returns: there is no way to change a single question on its own, so read the interview, edit that array, and send the whole thing back. An empty array is rejected. It is applied as a DIFF, not a replace, so resending the array job-interview-get gave you changes nothing at all. Each entry is matched against what is stored â\x80\x94 first on `external_id`, then on `id`, then on identical content â\x80\x94 and: an entry matching an unchanged question keeps that question exactly as it is, including its answer rules and any rendered avatar video; an entry matching a question whose content differs unlinks the old question and creates a new one in its place (fields you omit are carried over from the old one); an entry matching nothing is created; and a stored question no entry matches is unlinked. `questions_diff` in the response reports exactly what was decided. Questions are shared records, so nothing is ever deleted â\x80\x94 removing one only unlinks it from this interview, and an edit is always unlink-old + create-new so the change cannot leak into another interview reusing the same question. The welcome, thank-you and instructional-video steps are not part of this array and are left in place. Single-stage interviews only; for a multi-stage position, update its interview stages individually."}, 'recording': {'enum': ['audio_first_5_answers', 'audio_all', 'video_all', 'video_first_5_answers', None], 'type': ['string', 'null'], 'example': 'video_all', 'description': 'Cheating/proctoring detection mode for candidate answers â\x80\x94 this is NOT a full session recording. Video options also record the candidate. Omit/null to disable. Options â\x80\x94 `audio_first_5_answers`: Audio-only cheating detection, first 5 answers only. | `audio_all`: Audio-only cheating detection on every answer. | `video_all`: Audio + video cheating detection on every answer (candidate is recorded for all answers). | `video_first_5_answers`: Audio + video cheating detection, first 5 answers only..'}, 'coach_plan': {'enum': ['demo', 'screening', '2nd', '3rd', 'closing', 'job-specific', 'other', None], 'type': ['string', 'null'], 'example': 'screening', 'description': 'Coaching-plan stage this item belongs to, used by the coaching-plan progress view. Omit/null to leave it out of any plan. Options â\x80\x94 `demo`: Demo session. | `screening`: Screening-interview practice. | `2nd`: Second-interview practice. | `3rd`: Third-interview practice. | `closing`: Closing / salary-negotiation practice. | `job-specific`: Job-specific coaching. | `other`: Anything that does not fit the other buckets..'}, 'visibility': {'enum': ['merchant_public', 'merchant_invite', 'merchant_unlisted', None], 'type': ['string', 'null'], 'example': 'merchant_public', 'description': "Who can discover and access the interview. Options â\x80\x94 `merchant_public`: Listed on the merchant's public interview list â\x80\x94 anyone with the merchant link can find and start it. | `merchant_invite`: Invite-only â\x80\x94 only candidates explicitly invited (by email/link) can access it; not listed anywhere. | `merchant_unlisted`: Reachable only via a direct link â\x80\x94 not listed anywhere; share the link manually.."}, 'description': {'type': ['string', 'null'], 'description': 'Short interview description.'}, 'environment': {'enum': ['production', 'uat', 'development', 'demo', None], 'type': ['string', 'null'], 'example': 'production', 'description': 'Which of your webhook environments results from this interview are delivered to. Defaults to production. Options â\x80\x94 `production`: Live hiring. Results reach the webhooks configured as production. This is the default when the field is omitted. | `uat`: User-acceptance testing - an isolated environment for pre-release verification. | `development`: Development/testing. Use for interviews created by a test or preview app so their results never reach the production webhook. | `demo`: Demonstrations and sales trials..'}, 'position_id': {'type': ['string', 'null'], 'format': 'uuid', 'example': '00000000-0000-0000-0000-000000000000', 'minLength': 1, 'description': 'Id of the interview definition (single-stage) or position definition (multi-stage) to update. The same id you pass to job-interview-get.'}, 'result_view': {'enum': ['none', 'minimal', 'minimal_with_score', 'advanced', 'full', 'full_expand_scores', None], 'type': ['string', 'null'], 'example': 'full', 'description': 'Result screen shown to the candidate after finishing. With any value other than `none`, the candidate sees a results screen where they can provide feedback, record an intro video and edit the transcript, and must then submit the result; the value sets how much score/result detail is shown. Options â\x80\x94 `none`: No results screen at all â\x80\x94 the interview is submitted immediately when the candidate finishes (no feedback, intro video, transcript edit or manual submit step). | `minimal`: Minimal results layout, no score shown. | `minimal_with_score`: Minimal results layout including the overall score. | `advanced`: Advanced results layout with more detail. | `full`: Full results layout with all sections. | `full_expand_scores`: Full results with every score breakdown expanded..'}, 'type_credit': {'enum': ['resume_check', 'interview_coach_starter', 'interview_coach_contributor', 'interview_coach_manager', 'cover_letter', None], 'type': ['string', 'null'], 'example': 'interview_coach_manager', 'description': 'Credit bucket the session draws from. Only meaningful for candidate-paid coaching/persona sessions; hiring interviews and assessments are merchant-billed and carry null. Options â\x80\x94 `resume_check`: Resume-check credits. | `interview_coach_starter`: Coaching credits â\x80\x94 starter tier. | `interview_coach_contributor`: Coaching credits â\x80\x94 contributor tier. | `interview_coach_manager`: Coaching credits â\x80\x94 manager tier. | `cover_letter`: Cover-letter credits..'}, 'max_duration': {'type': ['number', 'null'], 'example': 1200, 'description': 'Live session limit in seconds. Also the basis for the credit multiplier.'}, 'max_followups': {'type': ['integer', 'null'], 'example': 2, 'maximum': 999.0, 'minimum': 0.0, 'description': 'Maximum number of AI follow-up questions. 0 disables follow-ups; presets are 0-3 (none/low/normal/high) and custom values start at 4; null uses the template default (Normal).'}, 'custom_scoring': {'type': ['object', 'null'], 'description': 'Result-scoring overrides (max_score, early_stop, speech_cadence, ai_pronunciation, sentiment_analysis, ai_assessment_answer, ai_assessment_resume, ai_assessment_session). Merged onto the stored configuration, so keys you omit keep their current value.', 'additionalProperties': {}}, 'interview_tone': {'enum': ['relaxed', 'simple', 'professional', 'persuasive', 'exact', None], 'type': ['string', 'null'], 'example': 'professional', 'description': "Tone â\x80\x94 configures the AI avatar's speaking style and the follow-up questions it generates. Stored in creation_parameters; existing questions are NOT regenerated. Case-insensitive; omit to default to relaxed. Options â\x80\x94 `relaxed`: Friendly and conversational tone that helps candidates feel at ease. | `simple`: Plain language at CEFR A2 level â\x80\x94 short sentences and simple words. | `professional`: Formal and business-like approach suitable for senior roles. | `persuasive`: Engaging style that encourages candidates to elaborate. | `exact`: Asks the questions exactly as provided, without rephrasing â\x80\x94 for interviews built from your own questions (create_interview_from_questions) where the wording is a script.."}, 'interview_type': {'enum': ['pre-screening', 'pre-screening-with-test-questions', 'second-interview', 'remote-freelancer-verification', 'strength-based-interview', 'potential-based-interview', 'process-verification-from-knowledge-base', None], 'type': ['string', 'null'], 'example': 'pre-screening-with-test-questions', 'description': 'Interview style â\x80\x94 configures the AI avatar and the follow-up questions it generates during the interview. Stored in creation_parameters; existing questions are NOT regenerated. Options â\x80\x94 `pre-screening`: Pre-screening â\x80\x94 quick qualification check focusing on basic requirements and availability. | `pre-screening-with-test-questions`: Pre-screening with test questions â\x80\x94 pre-screening plus practical questions to test relevant skills. | `second-interview`: Second round interview â\x80\x94 deeper dive for candidates who passed initial screening. | `remote-freelancer-verification`: Remote worker verification â\x80\x94 verify remote work capabilities and communication skills. | `strength-based-interview`: Strength-based interview â\x80\x94 focus on what candidates enjoy and excel at to predict job satisfaction. | `potential-based-interview`: Potential-based interview â\x80\x94 assess learning ability and growth potential rather than past experience. | `process-verification-from-knowledge-base`: Knowledge Base interview â\x80\x94 generate questions from your knowledge base documents..'}, 'conversation_id': {'type': 'string', 'description': "Pass the exact conversation_id from the server's previous response, unchanged. The server provides it on the first call â\x80\x94 never invent one, and do not issue parallel tool calls until you have it. Keep passing the same conversation_id for the rest of the conversation, including after later user messages or on a different task; do not reset it when the user starts a new request."}, 'cover_image_url': {'type': ['string', 'null'], 'description': 'Cover image URL.'}, 'seniority_level': {'enum': ['entry-level', 'intermediate', 'senior', 'managerial', 'director', 'executive', None], 'type': ['string', 'null'], 'example': 'senior', 'description': 'Target seniority level for the role; auto-detected from the job description when omitted. Options â\x80\x94 `entry-level`: Early-career or graduate roles. | `intermediate`: Some experience required. | `senior`: Experienced professional. | `managerial`: Team or department lead. | `director`: Director-level responsibility. | `executive`: C-suite or executive role..'}, 'description_long': {'type': ['string', 'null'], 'description': 'Long-form interview description (column `interview_description_long`). Rendered as Markdown on the candidate-facing position page, including chips, callouts, cards, columns and buttons â\x80\x94 formatting guide: https://developer.jobmojito.com/cookbooks/format-content-with-markdown'}, 'interview_salary': {'type': ['string', 'null'], 'example': '$80k - $100k', 'description': 'Salary range shown for the position. Blank is stored as null.'}, 'hiring_for_company': {'type': ['object', 'null'], 'example': {'name': 'undisclosed'}, 'properties': {'name': {'type': ['string', 'null'], 'example': 'Unimo Enterprises', 'description': "End-employer name. Omit/null when hiring for yourself, 'undisclosed' for an unnamed external client, or the client's company name."}, 'sector': {'type': ['string', 'null'], 'example': 'Logistics and Supply Chain', 'description': 'Industry / sector of the end employer.'}, 'location': {'type': ['string', 'null'], 'example': 'Sri Lanka', 'description': 'Primary location of the end employer.'}, 'description': {'type': ['string', 'null'], 'example': 'Unimo Enterprises is a leading logistics and supply chain solutions provider.', 'description': 'Short description of the end employer, used as background context by the agent.'}, 'company_size': {'type': ['string', 'null'], 'example': '100-200', 'description': 'Approximate headcount of the end employer.'}}, 'description': "Who the position is really for. null (or an object with name null/blank) means hiring for yourself; { name: 'undisclosed' } for an unnamed external client; or { name: '<company>' } plus optional description/location/sector/company_size. Stored in creation_parameters.hiring_for_company."}, 'interview_attempts': {'type': ['number', 'null'], 'example': 1, 'maximum': 20.0, 'minimum': 1.0, 'description': 'Allowed candidate attempts (1-20). Stored as result_scoring.max_retries.'}, 'country_availability': {'type': ['object', 'null'], 'properties': {'countries_allowed': {'type': ['array', 'null'], 'items': {'type': 'string', 'pattern': '^[A-Za-z]{2}$'}, 'example': ['PH', 'IN'], 'description': 'Available ONLY to candidates in these countries (ISO 3166-1 alpha-2).'}, 'countries_blocked': {'type': ['array', 'null'], 'items': {'type': 'string', 'pattern': '^[A-Za-z]{2}$'}, 'example': ['US'], 'description': 'NOT available to candidates in these countries (ISO 3166-1 alpha-2). Wins over the allowed side.'}, 'countries_allowed_eu': {'type': ['boolean', 'null'], 'description': 'Adds every EU country (plus EEA and Switzerland) to countries_allowed.'}, 'countries_blocked_eu': {'type': ['boolean', 'null'], 'description': 'Adds every EU country (plus EEA and Switzerland) to countries_blocked.'}}, 'description': 'Which countries the interview / position is open to on the candidate portal, judged by the IP address the candidate opens it from (an unknown location only passes when countries_allowed / countries_allowed_eu are empty). From a closed country it is left out of the portal listings, and a direct link shows "not available in your region". Invited candidates (register_users / invite links) and candidates who already started keep access; API and MCP calls themselves are never restricted. Null = not used, every country.'}, 'interview_department': {'type': ['string', 'null'], 'example': 'Engineering', 'description': 'Department the position belongs to. Blank is stored as null.'}, 'recruiter_profile_id': {'type': ['string', 'null'], 'description': 'Profile id of the recruiter owning this interview. Must be a merchant/merchant_owner/admin profile of the same merchant. null clears it.'}, 'interview_template_id': {'type': ['string', 'null'], 'example': '46b98d37-1557-4391-beca-03037ead19f2', 'minLength': 1, 'description': 'Id of the interview template (avatar/voice) to use. Must reference an existing interview_templates row. Also decides the modality â\x80\x94 see list_avatars / merchant-avatar-list.'}, 'candidate_expectations': {'type': ['string', 'null'], 'description': 'Free-text candidate expectations.'}, 'pdf_export_auto_config': {'type': ['object', 'null'], 'properties': {'files': {'type': ['boolean', 'null'], 'description': 'Include uploaded candidate files.'}, 'template': {'enum': ['classic', 'modern', 'one_pager', None], 'type': ['string', 'null'], 'description': 'Report layout: classic, modern, or one_pager. Omit for the merchant default (modern when unset).'}, 'analytics': {'type': ['boolean', 'null'], 'description': 'Include analytics.'}, 'transcript': {'type': ['boolean', 'null'], 'description': 'Include the interview transcript.'}, 'contact_details': {'type': ['boolean', 'null'], 'description': 'Include candidate contact details.'}, 'answer_recording': {'type': ['boolean', 'null'], 'description': 'Include per-answer recordings.'}, 'ai_scoring_rubric': {'type': ['boolean', 'null'], 'description': 'Include the AI scoring rubric.'}, 'group_by_question': {'type': ['boolean', 'null'], 'description': 'Group transcript answers by expected question.'}, 'session_recording': {'type': ['boolean', 'null'], 'description': 'Include the full-session recording.'}, 'mojito_language_code': {'enum': ['ar', 'bg', 'zh', 'hr', 'cs', 'da', 'nl', 'en', 'fil', 'fi', 'fr', 'de', 'el', 'hi', 'hu', 'id', 'it', 'ja', 'ko', 'ms', 'no', 'pl', 'pt', 'br', 'ro', 'ru', 'sk', 'es', 'sv', 'ta', 'th', 'tr', 'uk', 'vi', None], 'type': ['string', 'null'], 'example': 'en', 'description': 'Report language code (a platform-languages.json code).'}, 'ai_recruiter_assessment': {'type': ['boolean', 'null'], 'description': 'Include the AI recruiter assessment.'}}, 'description': 'Auto-generate a candidate PDF report with these options once the interview completes. null disables auto-export.'}, 'recording_full_session': {'enum': ['audio_all', 'video_all', None], 'type': ['string', 'null'], 'example': 'video_all', 'description': 'Full interview-session recording (includes the avatar and voice) produced as a single file. Independent of `recording`. Omit/null to disable. Options â\x80\x94 `audio_all`: Record the whole session audio (avatar + candidate voice) into a single file. Adds +0.2 credits. | `video_all`: Record the whole session video + audio (avatar + candidate) into a single file. Adds +0.4 credits..'}, 'required_pronunciation': {'type': ['boolean', 'null'], 'description': 'Require pronunciation assessment (restricts to pronunciation-capable languages).'}, 'knowledge_base_store_id': {'type': ['string', 'null'], 'description': 'Knowledge base store id the interview draws context from; validated for existence. null unlinks it.'}, 'questions_random_subset': {'type': ['number', 'null'], 'example': 0.5, 'maximum': 0.9, 'minimum': 0.01, 'description': 'Ask only a random subset of the questions, as a fraction between 0.01 and 0.9. null asks all questions.'}, 'interview_available_till': {'type': ['string', 'null'], 'example': '2026-12-31', 'description': 'ISO date/time after which the interview is no longer available to candidates. null keeps it always available.'}, 'candidate_expectations_json': {'type': ['object', 'null'], 'properties': {'weak': {'type': ['array', 'null'], 'items': {'type': 'string'}, 'description': 'Baseline requirements every viable candidate should meet (table stakes).'}, 'strong': {'type': ['array', 'null'], 'items': {'type': 'string'}, 'description': 'High-bar requirements only standout candidates clear.'}, 'moderate': {'type': ['array', 'null'], 'items': {'type': 'string'}, 'description': 'Requirements expected of a solid, competent candidate.'}}, 'description': 'Structured candidate expectations (the scoring rubric), bucketed by requirement level (weak/moderate/strong). null clears the rubric. Extra keys are preserved.'}, 'candidate_video_introduction': {'enum': ['hidden', 'optional', 'required', None], 'type': ['string', 'null'], 'description': 'Whether a candidate video introduction is hidden, optional or required. null is treated like hidden.'}, 'interview_conversation_speed': {'enum': ['slower', 'normal', 'faster', None], 'type': ['string', 'null'], 'example': 'normal', 'description': 'Conversation pace of the AI avatar. Omit/null keeps the template default pace. Options â\x80\x94 `slower`: The avatar speaks more slowly â\x80\x94 easier to follow for non-native speakers. | `normal`: Default speaking pace. | `faster`: The avatar speaks more quickly for a snappier conversation..'}, 'result_enable_edit_transcript': {'type': ['boolean', 'null'], 'description': 'Allow editing the transcript on the result view.'}, 'candidate_notification_channel': {'enum': ['reminders', 'last_reminder', 'all', None], 'type': ['string', 'null'], 'description': 'SMS / WhatsApp notifications to the candidate, sent alongside the e-mails: "reminders" = with both e-mail reminders (day 1 and day 3); "last_reminder" = only with the final day-3 reminder; "all" = invitation, both reminders and the pre-screening-accepted step. null switches them off. WhatsApp is tried first, SMS when the number is not on WhatsApp. Available on paid plans (Starter and above) and needs a phone number on the candidate.'}, 'regenerate_candidate_expectations': {'type': ['boolean', 'null'], 'example': False, 'description': 'Re-derive the interview-level `candidate_expectations_json` scoring rubric from the resulting question list, the way job-interview-create-from-array derives it at creation time. Only applies when `questions` is sent, the interview type is `interview`, and `candidate_expectations_json` is not also being set explicitly (an explicit value wins).'}}}
输出模式
{'type': 'object', 'required': ['position_id', 'is_multistage', 'updated_fields'], 'properties': {'position_id': {'type': ['string', 'null'], 'description': 'The id that was updated.'}, 'is_multistage': {'type': ['boolean', 'null'], 'description': 'True when the id resolved to a multi-stage position (position_def_set) rather than a single interview.'}, 'questions_diff': {'type': 'object', 'required': ['kept', 'added', 'removed', 'replaced', 'question_ids', 'reactivated'], 'properties': {'kept': {'type': ['array', 'null'], 'items': {'type': 'string'}, 'description': 'Questions left exactly as they were, record and all.'}, 'added': {'type': ['array', 'null'], 'items': {'type': 'string'}, 'description': 'Ids of the questions created for entries that matched nothing stored.'}, 'removed': {'type': ['array', 'null'], 'items': {'type': 'string'}, 'description': 'Ids unlinked because no entry in the request matched them. The question records themselves still exist.'}, 'replaced': {'type': ['array', 'null'], 'items': {'type': 'object', 'required': ['from', 'to'], 'properties': {'to': {'type': ['string', 'null'], 'description': 'The id of the question created in its place.'}, 'from': {'type': ['string', 'null'], 'description': 'The id that was unlinked.'}}}, 'description': 'Edited questions: the old record was unlinked and a new one created, so the change cannot leak into other interviews reusing it.'}, 'reactivated': {'type': ['boolean', 'null'], 'description': 'True when the interview was already active and was re-published so the new questions go live.'}, 'question_ids': {'type': ['array', 'null'], 'items': {'type': 'string'}, 'description': "The interview's full ordered step list after the update, including the welcome / thank-you / instructional steps this endpoint does not manage."}}, 'description': 'What the question diff decided, question by question. Absent when `questions` was not sent.'}, 'updated_fields': {'type': ['array', 'null'], 'items': {'type': 'string'}, 'example': ['name', 'tags'], 'description': 'Names of the stored columns that were written, plus `status` when the lifecycle status was changed and `questions` when the question list was diffed.'}, '_mcp_instructions': {'type': 'object', 'properties': {'conversation_id': {'type': 'string', 'description': 'The server-issued conversation identifier.'}}, 'description': 'Server-issued metadata for this conversation.'}}, 'description': 'Confirmation of what was updated.', 'x-fastmcp-top-level-schema': 'JobInterviewUpdateResponse'}
upload_knowledge_base_document
Upload knowledge base document
[Knowledge base] Upload and process a knowledge base document (multipart form-data). Uploads a document to a knowledge base store and queues it for processing. Accepts the file either as multipart/form-data (binary `file`) or as application/json (base64 `file`).
可能执行破坏性操作 可访问外部资源
输入模式
{'type': 'object', 'required': ['knowledge_base_store_id', 'file'], 'properties': {'file': {'type': ['string', 'null'], 'format': 'binary', 'description': 'The document file (binary).'}, 'name': {'type': ['string', 'null'], 'description': 'Document name (with extension). Falls back to the uploaded file name for multipart.'}, 'merchant_id': {'type': ['string', 'null'], 'description': 'Override merchant id (admin / sub-merchant only).'}, 'conversation_id': {'type': 'string', 'description': "Pass the exact conversation_id from the server's previous response, unchanged. The server provides it on the first call â\x80\x94 never invent one, and do not issue parallel tool calls until you have it. Keep passing the same conversation_id for the rest of the conversation, including after later user messages or on a different task; do not reset it when the user starts a new request."}, 'knowledge_base_store_id': {'type': ['string', 'null'], 'example': 'd9d6f121-1230-48fd-b3a7-8b5a1e8db052', 'minLength': 1, 'description': 'The knowledge base store to add the document to.'}}}
输出模式
{'type': 'object', 'required': ['knowledge_base_id'], 'properties': {'_mcp_instructions': {'type': 'object', 'properties': {'conversation_id': {'type': 'string', 'description': 'The server-issued conversation identifier.'}}, 'description': 'Server-issued metadata for this conversation.'}, 'knowledge_base_id': {'type': ['string', 'null'], 'description': 'Id of the created knowledge_base record.'}}, 'x-fastmcp-top-level-schema': 'KnowledgeBaseDocumentUploadResponse'}
已更改
update_interview
2026年10月1日 02:54
已更改
get_interview_definition
2026年10月1日 02:54
已更改
jobmojito_configuration
2026年9月29日 03:02
已更改
list_languages
2026年9月29日 03:02
已更改
get_merchant_status
2026年9月29日 03:02
已更改
list_avatars
2026年9月29日 03:02
已更改
list_sub_merchants
2026年9月29日 03:02
已更改
upload_knowledge_base_document
2026年9月29日 03:02
已更改
list_candidates
2026年9月29日 03:02
已更改
get_merchant_credit_usage
2026年9月29日 03:02
已更改
get_merchant_analytics
2026年9月29日 03:02
已更改
list_interview_results
2026年9月29日 03:02
已更改
request_another_interview_attempt
2026年9月29日 03:02
已更改
generate_interview_report
2026年9月29日 03:02
已更改
get_interview_result_details
2026年9月29日 03:02
已更改
list_catalogue_directories
2026年9月29日 03:02
已更改
get_catalogue_directory
2026年9月29日 03:02
已更改
update_catalogue_directory
2026年9月29日 03:02
已更改
create_catalogue_directory
2026年9月29日 03:02
已更改
list_interviews
2026年9月29日 03:02
已更改
register_users_for_interview
2026年9月29日 03:02
已更改
generate_interview_url
2026年9月29日 03:02
已更改
set_interview_state
2026年9月29日 03:02
已更改
update_interview
2026年9月29日 03:02
已更改
get_interview_definition
2026年9月29日 03:02
已更改
create_persona
2026年9月29日 03:02
已更改
create_interview_from_questions
2026年9月29日 03:02
已更改
create_interview
2026年9月29日 03:02
已更改
list_my_merchants
2026年9月29日 03:02
已更改
get_documentation
2026年9月29日 03:02