MCP 服务器

Zernote

com.zernote/zernote
知识与文档 搜索与研究 公开且可连接 MCP 2026-07-28

此 MCP 可以做什么

Uploads, transcribes, searches, codes, and analyzes interviews to produce evidence-linked insights and jobs-to-be-done research structures.

cards_read
Cards Read
List L2 coded claim-cards (claim + optional quote + chunk_index + lens + codes + start_seconds? + url). Filter by project_id, interview_id / interview_ids, codes (any match), or lens (workflow|gtm|privacy|other). CITATION REQUIRED: actively cite each card.quote to the user as markdown ["verbatim quote"]({base_url}/project/interview/{id}?t={seconds}) using item.url from the tool result (already absolute; includes ?t= when start_seconds is set). Prefer quotes over paraphrase. Verify with interviews_read action=transcript around_chunk_index when a wider quote window is needed.
只读
输入模式
{'type': 'object', 'properties': {'lens': {'enum': ['workflow', 'gtm', 'privacy', 'other'], 'type': 'string', 'description': 'Optional exact lens filter.'}, 'codes': {'type': 'array', 'items': {'type': 'string'}, 'description': 'Optional code tags; any match (e.g. pain:synthesis, gtm:pricing).'}, 'limit': {'type': 'integer', 'description': 'Max cards to return (default 50, max 200).'}, 'offset': {'type': 'integer', 'description': 'Number of cards to skip (default 0).'}, 'folder_id': {'type': 'string', 'description': 'Deprecated alias for project_id.'}, 'project_id': {'type': 'string', 'description': 'Optional project UUID — cards from interviews in this project (alias: folder_id).'}, 'interview_id': {'type': 'string', 'description': 'Optional interview UUID to scope cards.'}, 'interview_ids': {'type': 'array', 'items': {'type': 'string'}, 'description': 'Optional interview UUIDs to scope cards.'}}}
get-skills
Startup ideas / office hours
Use for startup ideas, office hours, and “I installed this connector to work through an idea”. Inside: office-hours-zernote (challenge the idea), zernote-plan-research. Omit id for the catalog, then pass id for the full playbook. Not for listing interviews or projects. Works without login.
只读
输入模式
{'type': 'object', 'properties': {'id': {'type': 'string', 'description': 'Skill id. Empty = catalog. Examples: office-hours-zernote, zernote-plan-research.'}}}
guides_create
Guides Create
Create the first interview guide on a project. Use this to upload a new guide. Pass structured fields, not markdown: intro, blocks (title, minutes, notes, questions with text/note/key), and notes_template. Needs at least one block with a title. Fails if the project already has a guide — then use guides_edit. Core does not show the guide. Live reads it on the project.
输入模式
{'type': 'object', 'required': ['project_id', 'blocks'], 'properties': {'intro': {'type': 'string', 'description': 'Spoken opening before the first block.'}, 'blocks': {'type': 'array', 'items': {'type': 'object', 'required': ['title'], 'properties': {'notes': {'type': 'string', 'description': 'Block note shown to the interviewer.'}, 'title': {'type': 'string', 'description': 'Block title, e.g. Opening.'}, 'minutes': {'type': 'integer', 'description': 'Minutes allocated to this block.'}, 'questions': {'type': 'array', 'items': {'type': 'object', 'required': ['text'], 'properties': {'key': {'type': 'boolean', 'description': 'True if this is a must-ask question.'}, 'note': {'type': 'string', 'description': 'Interviewer note under the question.'}, 'text': {'type': 'string', 'description': 'Spoken question.'}}}}}}, 'description': 'Timed sections in interview order.'}, 'project_id': {'type': 'string', 'description': 'Project UUID.'}, 'notes_template': {'type': 'string', 'description': 'Post-interview notes template (conspect).'}}}
guides_edit
Guides Edit
Replace an existing interview guide from markdown. To create the first guide, call guides_create. Text before the first ## is the intro. ## Title (12) or ## Title (7–11) is a block; minutes are the last number in parentheses. Lines starting with - or 1. are questions; a leading * marks a key question; the next indented line is the question note. A paragraph under the block heading before the first question is the block note. ## Конспект is the post-interview notes template, not a block. Optional line `Общее время: 30` or `Total: 30` sets total minutes; otherwise they are the sum of block minutes. Anything that does not match is returned in remainder and kept, not dropped. The previous guide is replaced entirely.
可能执行破坏性操作
输入模式
{'type': 'object', 'required': ['project_id', 'markdown'], 'properties': {'markdown': {'type': 'string', 'description': 'Full guide markdown. Replaces the guide stored on the project.'}, 'project_id': {'type': 'string', 'description': 'Project UUID.'}}}
guides_read
Guides Read
Read the interview guide stored on a project. The guide has an intro, ordered blocks (title, minutes, questions, notes), total time, a notes template, and any markdown that did not parse. Returns an empty guide when the project has none.
只读
输入模式
{'type': 'object', 'required': ['project_id'], 'properties': {'project_id': {'type': 'string', 'description': 'Project UUID.'}}}
insights_read
Insights Read
Read the project Insights graph in pages or by node. action=list returns a compact folder-wide outline (groups + interviews) plus a page of insight bodies. Filter with interview_id, group_id (DB UUID, not UI group-0), group_name, insight_ids, or ungrouped_only. action=get_node returns one node: insight | interview | group | ungrouped. CITATION REQUIRED: actively cite each item.quote as markdown ["verbatim quote"]({base_url}/project/interview/{id}?t={seconds}) using item.url from the tool result (already absolute; includes ?t= when start_seconds is set). Prefer quotes over paraphrase. Do not use quote_start — that is a character offset, not a player timestamp.
只读
输入模式
{'type': 'object', 'required': ['action'], 'properties': {'id': {'type': 'string', 'description': 'get_node: insight, interview, or group UUID. Not used for ungrouped.'}, 'limit': {'type': 'integer', 'description': 'List only: max insight bodies (default 25, max 100).'}, 'action': {'enum': ['list', 'get_node'], 'type': 'string', 'description': 'list = paged insight bodies + outline. get_node = one insight, interview, group, or ungrouped cluster.'}, 'offset': {'type': 'integer', 'description': 'List only: skip this many matching insight bodies (default 0).'}, 'group_id': {'type': 'string', 'description': 'List filter: insight_groups.id UUID (not a render index like group-0).'}, 'folder_id': {'type': 'string', 'description': 'Deprecated alias for project_id.'}, 'node_type': {'enum': ['insight', 'interview', 'group', 'ungrouped'], 'type': 'string', 'description': 'get_node: which node to load.'}, 'group_name': {'type': 'string', 'description': 'List filter: case-insensitive group name match.'}, 'project_id': {'type': 'string', 'description': 'Project/folder UUID (required for list and for get_node group/ungrouped/insight).'}, 'insight_ids': {'type': 'array', 'items': {'type': 'string'}, 'description': 'List filter: only these insight UUIDs.'}, 'interview_id': {'type': 'string', 'description': 'List filter: only insights from this interview. Interview must be in the project.'}, 'ungrouped_only': {'type': 'boolean', 'description': 'List filter: only insights that are not in a cross-interview group.'}}}
interviews_edit
Interviews Edit
Rename, move, write summary/notes, retranscribe, assign/confirm speakers, or toggle voiceprint. action=rename needs id+title; move needs interview_ids (+ optional project_id); write_summary needs id+summary; write_notes needs id+notes; retranscribe needs id+language (charges transcription tokens again; analyze-only, keeps notes). assign_speakers needs id+speaker_labels+assigned_names. For voiceprint interviewer confirm: one label + real name on one interview after quote links; that identity backfills other interviews sharing voice_identity_id — re-list instead of confirming every card. set_voiceprint needs enabled bool (false purges biometric voice data). If need_approve_speakers=true, show quote links then assign_speakers when the user confirms. If transcript_quality.looks_corrupted=true, offer retranscribe with the correct language. write_notes and write_summary replace the entire notes or summary field (not append).
可能执行破坏性操作
输入模式
{'type': 'object', 'required': ['action'], 'properties': {'id': {'type': 'string', 'description': 'Interview UUID (rename, write_summary, write_notes, retranscribe, assign_speakers).'}, 'notes': {'type': 'string', 'description': 'Full note text that replaces the existing notes field (write_notes).'}, 'title': {'type': 'string', 'description': 'New title (rename).'}, 'action': {'enum': ['rename', 'move', 'write_summary', 'write_notes', 'retranscribe', 'assign_speakers', 'set_voiceprint'], 'type': 'string', 'description': 'Edit action.'}, 'enabled': {'type': 'boolean', 'description': 'Voiceprint on/off (set_voiceprint). false deletes stored voice biometrics.'}, 'summary': {'type': 'string', 'description': 'Full summary markdown that replaces the existing summary (write_summary). Expected sections: # Summary, ## Profile, ## Tools & workflow, ## Pains & friction, # Other topics.'}, 'language': {'type': 'string', 'description': 'Transcription language code for retranscribe (e.g. en, ru, nl). Charges tokens for audio duration.'}, 'folder_id': {'type': 'string', 'description': 'Deprecated alias for project_id.'}, 'project_id': {'type': 'string', 'description': 'Destination project UUID for move (alias: folder_id). Omit or null for Inbox.'}, 'interview_ids': {'type': 'array', 'items': {'type': 'string'}, 'description': 'Interview UUIDs to move.'}, 'assigned_names': {'type': 'array', 'items': {'type': 'string'}, 'description': 'Human names matching speaker_labels (assign_speakers). Use a real name, not "Interviewer N".'}, 'speaker_labels': {'type': 'array', 'items': {'type': 'string'}, 'description': 'Diarization labels to assign (assign_speakers), e.g. ["A"]. Voiceprint interviewer confirm: one label in this call (same identity then backfills other interviews).'}}}
interviews_read
Interviews Read
Read interviews. Typical path: (1) action=list with summary_mode=brief (default) — returns the short # Summary. List items include need_approve_speakers (+ pending_speakers / hint): when true, show interviewer quote links then confirm via assign_speakers; one identity confirm backfills other interviews sharing voice_identity_id. Use summary_mode=brief for renaming or folder triage. Use summary_mode=full when Profile/Tools/Pains/Other topics are needed for deeper analysis. (2) call `search` when you need evidence or counter-evidence for a hypothesis; (3) use action=transcript with around_chunk_index from matching_chunks when a quote window is required. CITATION REQUIRED: when answering the user, actively cite evidence as markdown ["verbatim quote"]({base_url}/project/interview/{id}?t={seconds}) using interview_url / matching chunk url from tool results (includes ?t= when start_seconds is set). Prefer quotes over paraphrase.
只读
输入模式
{'type': 'object', 'required': ['action'], 'properties': {'id': {'type': 'string', 'description': 'Interview UUID (required for get, status, transcript).'}, 'limit': {'type': 'integer', 'description': 'For list: max interviews (default 20, max 100). For transcript: max characters (default 4000, max 20000).'}, 'action': {'enum': ['list', 'get', 'status', 'transcript'], 'type': 'string', 'description': 'Read action. Use list (brief or summary_mode=full) for overview; use transcript when you need a quote window.'}, 'offset': {'type': 'integer', 'description': 'For list: skip count. For transcript without around_chunk_index: character offset (default 0).'}, 'folder_id': {'type': 'string', 'description': 'Deprecated alias for project_id.'}, 'inbox_only': {'type': 'boolean', 'description': 'When true with action=list, list Inbox interviews (no project). Ignored if project_id is set.'}, 'notes_mode': {'enum': ['none', 'full'], 'type': 'string', 'description': 'List only. none (default) = omit notes body. full = researcher notes (truncated on list). Use summary when notes are not required.'}, 'project_id': {'type': 'string', 'description': 'Optional project UUID to filter list (alias: folder_id).'}, 'radius_chars': {'type': 'integer', 'description': 'Transcript only with around_chunk_index: chars before/after chunk match (default 1500, max 8000).'}, 'summary_mode': {'enum': ['brief', 'full'], 'type': 'string', 'description': 'List only. brief (default) = short # Summary for triage/rename. full = all summary_fragments (profile/tools/pains/other_topics) when brief is insufficient.'}, 'around_chunk_index': {'type': 'integer', 'description': 'Transcript only: expand a window around this vector-search chunk_index (use instead of blind offset when available).'}}}
jtbd_edit
JTBD Edit
Edit JTBD graph: extract_interview, move_interview, create_segment, fill_in job, update_job, delete_job.
可能执行破坏性操作
输入模式
{'type': 'object', 'required': ['action'], 'properties': {'name': {'type': 'string'}, 'when': {'type': 'string'}, 'action': {'enum': ['extract_interview', 'move_interview', 'create_segment', 'fill_in', 'update_job', 'delete_job'], 'type': 'string'}, 'job_id': {'type': 'string'}, 'so_that': {'type': 'string'}, 'category': {'type': 'string'}, 'language': {'type': 'string', 'description': 'Job tree language for extract_interview (en or ru). Defaults to en. Quotes stay in the interview language.'}, 'folder_id': {'type': 'string'}, 'i_want_to': {'type': 'string'}, 'project_id': {'type': 'string'}, 'segment_id': {'type': 'string'}, 'human_edited': {'type': 'boolean'}, 'interview_id': {'type': 'string'}, 'to_segment_id': {'type': 'string'}}}
jtbd_read
JTBD Read
Read JTBD job graph segments and trees. action=list_segments needs folder_id/project_id. action=get_tree needs segment_id or interview_id. CITATION REQUIRED: cite job quotes as ["text"](interview_url).
只读
输入模式
{'type': 'object', 'required': ['action'], 'properties': {'action': {'enum': ['list_segments', 'get_tree'], 'type': 'string'}, 'folder_id': {'type': 'string', 'description': 'Project/folder UUID (list_segments).'}, 'project_id': {'type': 'string', 'description': 'Alias for folder_id.'}, 'segment_id': {'type': 'string', 'description': 'Segment UUID (get_tree).'}, 'interview_id': {'type': 'string', 'description': 'Interview UUID (get_tree).'}}}
mcp_confirm_upload
Confirm Upload
App-only: confirm a completed R2 upload (single PUT or multipart) for an Inbox interview. Audio/video is enqueued for transcription (STT + diarization). Text (.txt/.md) and PDF are stored and marked ready immediately — no transcription.
输入模式
{'type': 'object', 'required': ['interview_id', 'object_key', 'filename', 'size_bytes', 'language'], 'properties': {'title': {'type': 'string', 'description': 'Optional title to apply before confirm.'}, 'filename': {'type': 'string', 'description': 'Original filename.'}, 'language': {'type': 'string', 'description': 'STT language for audio/video (e.g. en, ru, nl). Not used for text/PDF (no transcription).'}, 'object_key': {'type': 'string', 'description': 'R2 object key from prepare.'}, 'size_bytes': {'type': 'integer', 'description': 'File size in bytes.'}, 'interview_id': {'type': 'string', 'description': 'Interview UUID from prepare.'}, 'multipart_parts': {'type': 'array', 'items': {'type': 'object', 'properties': {'etag': {'type': 'string'}, 'part_number': {'type': 'integer'}}}, 'description': 'Completed parts (part_number + etag) when using multipart.'}, 'multipart_upload_id': {'type': 'string', 'description': 'Multipart upload id — complete assembly before confirm.'}}}
mcp_prepare_upload
Prepare Upload
App-only: create an Inbox interview and return a presigned R2 upload URL (or multipart upload_id for large files). Pass interview_id (+ upload_id for multipart) to resume without a new card.
输入模式
{'type': 'object', 'required': ['filename', 'size_bytes'], 'properties': {'title': {'type': 'string', 'description': 'Optional interview title (defaults to sanitized filename).'}, 'filename': {'type': 'string', 'description': 'Original filename.'}, 'upload_id': {'type': 'string', 'description': 'Optional multipart upload id from a previous prepare (resume).'}, 'size_bytes': {'type': 'integer', 'description': 'File size in bytes.'}, 'content_type': {'type': 'string', 'description': 'MIME type for the PUT (optional).'}, 'interview_id': {'type': 'string', 'description': 'Optional: existing empty interview UUID — resume upload without creating a new card.'}}}
mcp_sign_upload_parts
Sign Upload Parts
App-only: return presigned R2 URLs for one or more multipart upload parts (resume-safe).
输入模式
{'type': 'object', 'required': ['interview_id', 'object_key', 'upload_id', 'part_numbers'], 'properties': {'upload_id': {'type': 'string', 'description': 'Multipart upload id from prepare.'}, 'object_key': {'type': 'string', 'description': 'R2 object key from prepare.'}, 'interview_id': {'type': 'string', 'description': 'Interview UUID from prepare.'}, 'part_numbers': {'type': 'array', 'items': {'type': 'integer'}, 'description': 'Part numbers to sign (1-based, max 20).'}}}
projects_edit
Projects Edit
Create or rename projects. action=create needs name; action=rename needs id and name. Delete is not supported yet.
输入模式
{'type': 'object', 'required': ['action'], 'properties': {'id': {'type': 'string', 'description': 'Project UUID (required for rename).'}, 'name': {'type': 'string', 'description': 'Project name (required for create and rename).'}, 'action': {'enum': ['create', 'rename'], 'type': 'string', 'description': 'Edit action.'}, 'description': {'type': 'string', 'description': 'Optional project description (create/rename).'}}}
projects_read
Projects Read
Read existing research folders. Not for a new startup idea or office hours — call get-skills first. action=list returns projects for the authenticated user.
只读
输入模式
{'type': 'object', 'required': ['action'], 'properties': {'limit': {'type': 'integer', 'description': 'Max number of projects to return (default 50, max 200).'}, 'action': {'enum': ['list'], 'type': 'string', 'description': 'Read action. Currently only list.'}, 'offset': {'type': 'integer', 'description': 'Number of projects to skip before returning results (default 0).'}}}
search
Search
Semantic search for evidence / counter-evidence after you have interview context (e.g. from list/summary). Optional interview_id scopes search to one interview and returns smaller text windows. Returns matching_chunks[{chunk_index, text, similarity, start_seconds?, url}]. CITATION REQUIRED: actively cite hits to the user as markdown ["verbatim quote from text"]({base_url}/project/interview/{id}?t={seconds}) using each chunk's url field from the tool result (already absolute; includes ?t= when start_seconds is present). Prefer quoting matching_chunks over paraphrase. Expand with interviews_read action=transcript around_chunk_index when a wider quote window is needed.
只读
输入模式
{'type': 'object', 'required': ['query'], 'properties': {'limit': {'type': 'integer', 'description': 'Max number of interviews to return (default 5, max 10). Ignored when interview_id is set.'}, 'query': {'type': 'string', 'description': 'Natural language search query (hypothesis / claim to evidence).'}, 'chunks_limit': {'type': 'integer', 'description': 'Max matching chunks per interview (default 3 corpus / 8 when interview_id set; max 10 / 20).'}, 'interview_id': {'type': 'string', 'description': 'Optional interview UUID — search only inside this interview; returns smaller chunk windows.'}, 'chunks_offset': {'type': 'integer', 'description': 'Skip this many top chunks per interview (default 0).'}}}
upload_interview
Upload Interview
Opens the in-Claude MCP Apps widget "Upload To Zernote" so the user can drop a file into Inbox in this chat (audio/video max 2GB; text .txt/.md or PDF max 50MB). Use when the user wants to upload/add an interview or get started on an empty account — this is the usual ingest path in Claude. Audio/video starts transcription; text/PDF become ready immediately (no speaker diarization). Claude can name interviews after upload.
输入模式
{'type': 'object', 'properties': {}}
已添加
guides_edit
2026年10月1日 02:42
已添加
guides_create
2026年10月1日 02:42
已添加
guides_read
2026年10月1日 02:42
已添加
mcp_confirm_upload
2026年9月25日 02:40
已添加
mcp_sign_upload_parts
2026年9月25日 02:40
已添加
mcp_prepare_upload
2026年9月25日 02:40
已添加
upload_interview
2026年9月25日 02:40
已添加
jtbd_edit
2026年9月25日 02:40
已添加
jtbd_read
2026年9月25日 02:40
已添加
insights_read
2026年9月25日 02:40
已添加
cards_read
2026年9月25日 02:40
已添加
search
2026年9月25日 02:40
已添加
interviews_edit
2026年9月25日 02:40
已添加
interviews_read
2026年9月25日 02:40
已添加
projects_edit
2026年9月25日 02:40
已添加
projects_read
2026年9月25日 02:40
已添加
get-skills
2026年9月25日 02:40