@sura_ai/mcp-server 0.1.4 → 0.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +19 -9
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -38,10 +38,10 @@ Title: ${W.title}
|
|
|
38
38
|
ID: ${W.documentId}`},getLogMessage:(W)=>`Creating document: "${W.title.slice(0,30)}${W.title.length>30?"...":""}"`})}function BD(Q,X,W=150){let G=0,Y=Math.min(Q.length,X.length);while(G<Y&&Q[G]===X[G])G++;let H=0;while(H<Y-G&&Q[Q.length-1-H]===X[X.length-1-H])H++;let J=Q.slice(G,Q.length-H||void 0),B=X.slice(G,X.length-H||void 0),$=Math.floor(W/2),q=Math.max(0,G-$),z=Math.min(Q.length,Q.length-H+$),V=Math.min(X.length,X.length-H+$),A=q>0?"...":"",U=z<Q.length?"...":"",D=V<X.length?"...":"",L=`${A}${Q.slice(q,z)}${U}`,E=`${A}${X.slice(q,V)}${D}`;return`--- before
|
|
39
39
|
${L}
|
|
40
40
|
+++ after
|
|
41
|
-
${E}`}function E6(Q){if(!Q)return"";let X=[];if(Q.previousBlock)X.push(`After: [${Q.previousBlock.type} | ${Q.previousBlock.id
|
|
42
|
-
`)}let G=[];if(W.deletedBlock){let{blockType:H,contentPreview:J}=W.deletedBlock;if(G.push(`Deleted [${H} | ${W.deletedBlock.blockId
|
|
43
|
-
`)},getLogMessage:(W)=>{if(W.blockIds&&W.blockIds.length>0)return`${W.entityType}/${W.entityId.slice(0,8)} batch delete ${W.blockIds.length} blocks`;return`${W.entityType}/${W.entityId.slice(0,8)} block ${W.blockId?.slice(0,8)??"unknown"}`}})}var GC=R.object({entityId:R.string().
|
|
44
|
-
`)}var JC=R.object({forceRefresh:R.boolean().optional().describe("Force reload from server instead of returning cached context. Use after creating new organizations or workspaces.")}),BC={name:"get_workspace_context",description:"Get the user's organizational hierarchy: organizations, workspaces, and spaces. Returns default orgId and workspaceId for use with other tools (search, create_document, etc.). Called automatically at startup; use forceRefresh=true to reload if the user creates new workspaces mid-session."};function VD(Q,X){L1(Q,X,{definition:BC,schema:JC,createExecutor:(W)=>{return async(G)=>{if(W.workspaceContext&&!G.forceRefresh)return W.workspaceContext;let Y=await W.client.getWorkspaceContext();return W.workspaceContext=Y,Y}},formatOutput:(W)=>JSON.stringify(W,null,2),getLogMessage:(W)=>W.forceRefresh?"force refresh":"cached"})}var UD=["paragraph","heading","bulletListItem","numberedListItem","checkListItem","codeBlock","quote","referenceList","annotationList","referenceItem"],DD=["literature","document","record","annotation"],AD=50,$C=R.object({blockType:R.enum(UD).default("paragraph").describe("Type of block to create. Default: paragraph"),content:R.string().describe("Text content for the block"),headingLevel:R.number().int().min(1).max(3).optional().describe("Heading level (1-3) if blockType is heading"),checked:R.boolean().optional().describe("Checked state for checkListItem"),title:R.string().optional().describe('Title for referenceList container (default: "References")'),refNumber:R.number().int().min(1).optional().describe("Reference number for referenceItem (e.g., 1, 2, 3)"),refId:R.string().optional().describe('Stable ref ID for citation linking (e.g., "
|
|
41
|
+
${E}`}function E6(Q){if(!Q)return"";let X=[];if(Q.previousBlock)X.push(`After: [${Q.previousBlock.type} | ${Q.previousBlock.id}]`);if(Q.nextBlock)X.push(`Before: [${Q.nextBlock.type} | ${Q.nextBlock.id}]`);return X.join(", ")}var $D=50,XC=R.object({entityType:R.enum(["document","record"]).describe('Entity type: "document" or "record"'),entityId:R.string().uuid().describe("Document or record ID"),blockId:R.string().optional().describe("Block ID to delete (for single delete)"),blockIds:R.array(R.string()).max($D).optional().describe(`Array of block IDs to delete (batch mode, max ${$D})`)}),WC={name:"delete_block",description:"Delete blocks from a document. Supports single (blockId) or batch (blockIds) mode. Batch mode is more efficient for deleting multiple blocks in one operation. Be careful - this permanently removes blocks and their content. Use get_content first to verify blocks before deleting."};function qD(Q,X){L1(Q,X,{definition:WC,schema:XC,createExecutor:(W)=>{return async(G)=>{return await W.client.deleteBlock(G)}},formatOutput:(W)=>{if(!W.success)return`Delete failed: ${W.error}`;if(W.deletedBlockIds&&W.deletedBlockIds.length>0){let H=[`Deleted ${W.deletedBlockIds.length} blocks:`];if(W.results){for(let J of W.results)if(J.success){let B=J.blockType??"?",$=J.contentPreview?`: ${J.contentPreview.slice(0,60)}${J.contentPreview.length>60?"...":""}`:"";H.push(` [${B} | ${J.blockId}]${$}`)}}return H.join(`
|
|
42
|
+
`)}let G=[];if(W.deletedBlock){let{blockType:H,contentPreview:J}=W.deletedBlock;if(G.push(`Deleted [${H} | ${W.deletedBlock.blockId}]`),J)G.push(`Was: ${J}`)}else G.push("Block deleted");let Y=E6(W.positionContext);if(Y)G.push(`New adjacency: ${Y}`);return G.join(`
|
|
43
|
+
`)},getLogMessage:(W)=>{if(W.blockIds&&W.blockIds.length>0)return`${W.entityType}/${W.entityId.slice(0,8)} batch delete ${W.blockIds.length} blocks`;return`${W.entityType}/${W.entityId.slice(0,8)} block ${W.blockId?.slice(0,8)??"unknown"}`}})}var GC=R.object({entityId:R.string().describe('Entity ID (UUID or short ref like "lit-a3f7e2b9")'),overview:R.boolean().optional().describe("Return overview with TOC and preview. Default behavior."),blockIds:R.array(R.string()).optional().describe("Array of specific block IDs to fetch from search results"),section:R.string().optional().describe('Section heading text, blockId, or parent-qualified path (e.g., "Methods/Key Takeaways") to fetch all blocks from'),refs:R.array(R.number().int()).optional().describe("Reference numbers to fetch (e.g., [42, 43])"),figures:R.array(R.string()).optional().describe('Figure IDs to fetch (e.g., ["fig-1", "fig-2"])'),tables:R.array(R.string()).optional().describe('Table IDs to fetch (e.g., ["table-1"])'),depth:R.number().int().min(0).optional().describe("Section depth: 0 = only blocks directly under this heading (no children), 1 = include immediate children, undefined = all descendants (default). Only used with section parameter."),from_section:R.string().optional().describe('Start section heading, blockId, or parent-qualified path (e.g., "Parent/Section") for range fetching (inclusive). Use with to_section.'),to_section:R.string().optional().describe('End section heading, blockId, or parent-qualified path (e.g., "Parent/Section") for range fetching (inclusive). Use with from_section.')}),YC={name:"get_content",description:'Fetch content from literature, documents, or records. Returns markdown text.\nAccepts full UUIDs or short entity reference IDs (e.g., `lit-a3f7e2b9`, `doc-9bk4x1f2`, `rec-f72mn3a8`).\n\n**Modes:**\n1. **Overview** (default): Preview + table of contents with section headings and estimated tokens.\n2. **Section**: Pass `section="Heading Name"` to get all blocks in that section as interleaved markdown.\n3. **Block IDs**: Pass `blockIds=["id1","id2"]` to fetch specific blocks from search results.\n4. **Refs**: Pass `refs=[42,43]` to fetch literature references by number.\n5. **Figures**: Pass `figures=["fig-1"]` to fetch figure blocks.\n6. **Tables**: Pass `tables=["table-1"]` to fetch table blocks.\n7. **Section range**: Pass `from_section` and `to_section` to fetch all content between two headings (inclusive).\n8. **Section with depth**: Pass `section` with `depth=0` for own content only, `depth=1` for immediate children.\n\n**Interleaved Format (Section mode):**\nSection mode returns content with block IDs embedded for editing:\n```\n[paragraph | dff74a60-0dd9-4cfa-9ae1-04c462d5cf46]\nThis is the paragraph content...\n\n[heading:2 | a9fe6c59-cf59-495c-b688-a6fcfb605491]\n## Methods\n```\nUse these block IDs with `str_replace_block`, `insert_block`, or `delete_block`.\n\n**Reading Strategy:** Check `ownTokens` and `children` in TOC entries:\n- If `ownTokens` is 0 and `children` exists → container heading, fetch children individually\n- If `children` is absent → leaf section, fetch directly with `section`\n- `estimatedTokens` = total tokens including all descendants\n\n**Best Practice:** Check `estimatedTokens` in TOC before fetching large sections.'};function zD(Q,X){HD(Q,X,{definition:YC,schema:GC,createExecutor:(W)=>{return async(G)=>{return W.client.getContent(G)}},formatSuccess:HC,formatNotFound:(W)=>JSON.stringify({found:!1,error:W.error??"Entity not found"}),getLogMessage:(W)=>{let G=W.blockIds?`blocks:${W.blockIds.length}`:W.from_section&&W.to_section?`range:"${W.from_section}"-"${W.to_section}"`:W.section?`section:"${W.section}"${W.depth!==void 0?`,depth=${W.depth}`:""}`:W.refs?`refs:${W.refs.length}`:"overview";return`${W.entityId.slice(0,8)}... (${G})`}})}function HC(Q){let X=[];if(X.push(`**"${Q.entityTitle}"** - ${Q.entityType}`),Q.overview){if(Q.overview.wordCount)X.push(`*~${Q.overview.wordCount} words*`);if(X.push(""),Q.overview.abstract)X.push("**Preview:**"),X.push(Q.overview.abstract),X.push("");if(Q.overview.toc&&Q.overview.toc.length>0)X.push("**Table of Contents:**"),X.push("```json"),X.push(JSON.stringify(Q.overview.toc,null,2)),X.push("```")}if(Q.markdown){if(X.push(""),Q.format==="interleaved")X.push("**Content (with block IDs for editing):**");else X.push("**Markdown Content:**");X.push(""),X.push(Q.markdown)}if(Q.sectionInfo){if(X.push(""),X.push(`*Section: ${Q.sectionInfo.blockCount} blocks, ${Q.sectionInfo.wordCount} words*`),Q.sectionInfo.warning)X.push(`*Warning: ${Q.sectionInfo.warning}*`)}if(Q.refs&&Q.refs.length>0)X.push(""),X.push("**References:**"),X.push("```json"),X.push(JSON.stringify(Q.refs,null,2)),X.push("```");return X.join(`
|
|
44
|
+
`)}var JC=R.object({forceRefresh:R.boolean().optional().describe("Force reload from server instead of returning cached context. Use after creating new organizations or workspaces.")}),BC={name:"get_workspace_context",description:"Get the user's organizational hierarchy: organizations, workspaces, and spaces. Returns default orgId and workspaceId for use with other tools (search, create_document, etc.). Called automatically at startup; use forceRefresh=true to reload if the user creates new workspaces mid-session."};function VD(Q,X){L1(Q,X,{definition:BC,schema:JC,createExecutor:(W)=>{return async(G)=>{if(W.workspaceContext&&!G.forceRefresh)return W.workspaceContext;let Y=await W.client.getWorkspaceContext();return W.workspaceContext=Y,Y}},formatOutput:(W)=>JSON.stringify(W,null,2),getLogMessage:(W)=>W.forceRefresh?"force refresh":"cached"})}var UD=["paragraph","heading","bulletListItem","numberedListItem","checkListItem","codeBlock","quote","divider","referenceList","annotationList","referenceItem"],DD=["literature","document","record","annotation"],AD=50,$C=R.object({blockType:R.enum(UD).default("paragraph").describe("Type of block to create. Default: paragraph"),content:R.string().describe("Text content for the block"),headingLevel:R.number().int().min(1).max(3).optional().describe("Heading level (1-3) if blockType is heading"),checked:R.boolean().optional().describe("Checked state for checkListItem"),title:R.string().optional().describe('Title for referenceList container (default: "References")'),refNumber:R.number().int().min(1).optional().describe("Reference number for referenceItem (e.g., 1, 2, 3)"),refId:R.string().optional().describe('Stable ref ID for citation linking (e.g., "lit-a3f7e2b9"). Auto-generated from linkedEntityId if omitted.'),refType:R.enum(DD).optional().describe("Type of reference: literature, document, record, or annotation"),linkedEntityId:R.string().uuid().optional().describe("UUID of the linked entity (literature, document, or record)"),entityTitle:R.string().optional().describe("Cached title of the linked entity"),doi:R.string().optional().describe("DOI for literature references")}),qC=R.object({entityType:R.enum(["document","record"]).describe('Entity type: "document" or "record"'),entityId:R.string().uuid().describe("Document or record ID"),afterBlockId:R.string().optional().describe("Insert AFTER this block ID (sibling insertion)"),beforeBlockId:R.string().optional().describe("Insert BEFORE this block ID (sibling insertion)"),parentBlockId:R.string().optional().describe("Insert as CHILD of this container block (e.g., add referenceItem inside referenceList)"),childPosition:R.string().optional().describe('Position within parent children: "first", "last" (default), or child block ID to insert after'),blockType:R.enum(UD).default("paragraph").optional().describe("Type of block to create. Default: paragraph"),content:R.string().optional().describe("Text content for the new block"),headingLevel:R.number().int().min(1).max(3).optional().describe("Heading level (1-3) if blockType is heading"),checked:R.boolean().optional().describe("Checked state for checkListItem"),title:R.string().optional().describe('Title for referenceList container (default: "References")'),refNumber:R.number().int().min(1).optional().describe("Reference number for referenceItem (e.g., 1, 2, 3)"),refId:R.string().optional().describe('Stable ref ID for citation linking (e.g., "lit-a3f7e2b9"). Auto-generated from linkedEntityId if omitted.'),refType:R.enum(DD).optional().describe("Type of reference: literature, document, record, or annotation"),linkedEntityId:R.string().uuid().optional().describe("UUID of the linked entity (literature, document, or record)"),entityTitle:R.string().optional().describe("Cached title of the linked entity"),doi:R.string().optional().describe("DOI for literature references"),blocks:R.array($C).max(AD).optional().describe(`Array of blocks to insert in sequence. Max ${AD} blocks. Use this for inserting multiple blocks in one call.`)}),zC={name:"insert_block",description:`Insert block(s) in a document. Three positioning modes:
|
|
45
45
|
1. afterBlockId: Insert as SIBLING after the specified block
|
|
46
46
|
2. beforeBlockId: Insert as SIBLING before the specified block
|
|
47
47
|
3. parentBlockId: Insert as CHILD of a container block (e.g., referenceItem inside referenceList)
|
|
@@ -51,15 +51,16 @@ Single mode: provide content and optional blockType.
|
|
|
51
51
|
Batch mode: provide blocks array for multiple blocks in one call (more efficient).
|
|
52
52
|
|
|
53
53
|
**Supported block types:**
|
|
54
|
-
- Content: paragraph, heading (with headingLevel 1-3), bulletListItem, numberedListItem, checkListItem, codeBlock, quote
|
|
54
|
+
- Content: paragraph, heading (with headingLevel 1-3), bulletListItem, numberedListItem, checkListItem, codeBlock, quote, divider (horizontal rule, no content needed)
|
|
55
55
|
- Containers: referenceList (bibliography), annotationList (free-text notes)
|
|
56
56
|
- Items: referenceItem (goes inside containers)
|
|
57
57
|
|
|
58
58
|
**Reference Lists (Bibliography) - numbered citations [1], [2]:**
|
|
59
59
|
1. Create container: \`insert_block(afterBlockId="...", blockType="referenceList", title="References", content="")\`
|
|
60
60
|
2. Add items using \`parentBlockId\`:
|
|
61
|
-
\`insert_block(parentBlockId="<container-id>", blocks=[{blockType:"referenceItem", linkedEntityId:"<uuid>", refNumber:1,
|
|
62
|
-
-
|
|
61
|
+
\`insert_block(parentBlockId="<container-id>", blocks=[{blockType:"referenceItem", linkedEntityId:"<uuid>", refNumber:1, refType:"literature", content:""}])\`
|
|
62
|
+
- refId is auto-generated as \`{type}-{uuid8}\` (e.g., \`lit-a3f7e2b9\`) from linkedEntityId + refType
|
|
63
|
+
- For SURA entities: provide \`linkedEntityId\` - metadata and refId auto-populate
|
|
63
64
|
- For external sources: provide full \`content\` with citation text
|
|
64
65
|
- refType: literature | document | record
|
|
65
66
|
|
|
@@ -70,7 +71,16 @@ Batch mode: provide blocks array for multiple blocks in one call (more efficient
|
|
|
70
71
|
|
|
71
72
|
**IMPORTANT:** Use \`parentBlockId\` for referenceItem blocks. Using \`afterBlockId\` places them OUTSIDE the container (wrong).
|
|
72
73
|
|
|
73
|
-
|
|
74
|
+
**SURA Markdown Syntax (used in content fields):**
|
|
75
|
+
|
|
76
|
+
*Inline styling:* **bold**, *italic*, ~~strike~~, \`code\`, {u}underline{/u}, {color:red}text color{/color}, {bg:yellow}background{/bg}
|
|
77
|
+
Colors (text and background): default, gray, brown, red, orange, yellow, green, blue, purple, pink
|
|
78
|
+
|
|
79
|
+
*Citations:* \`[[citation:["lit-a3f7e2b9"]|[1]]]\` or \`[[citation:["lit-a3f7e2b9","doc-9bk4x1f2"]|[1,2]]]\` — refIds match referenceItem refId props
|
|
80
|
+
*Mentions:* \`[[mention:document:uuid|Title]]\` — entity types: document, record, literature
|
|
81
|
+
*Figure/Table refs:* \`[[figureRef:targetId:blockId|Figure 1]]\`, \`[[tableRef:targetId:blockId|Table 1]]\`
|
|
82
|
+
*Molecules:* \`:::molecule{structureType=molecule smiles="CCO" name="Ethanol"}:::\` — use valid SMILES notation
|
|
83
|
+
*Reactions:* \`:::molecule{structureType=reaction smiles="CC(=O)C.N>>CC(N)C.O"}:::\` — reactants>>products in SMILES`};function KD(Q,X){L1(Q,X,{definition:zC,schema:qC,createExecutor:(W)=>{return async(G)=>{return await W.client.insertBlock(G)}},formatOutput:(W)=>{if(!W.success)return`Insert failed: ${W.error}`;if(W.newBlockIds&&W.newBlockIds.length>0){let H=[`Inserted ${W.newBlockIds.length} blocks:`];if(W.results){for(let J of W.results)if(J.success&&J.newBlockId){let B=J.blockType??"paragraph",$=J.contentPreview?`: ${J.contentPreview.slice(0,60)}${J.contentPreview.length>60?"...":""}`:"";H.push(` [${B} | ${J.newBlockId}]${$}`)}}return H.join(`
|
|
74
84
|
`)}let G=[`Block inserted. ID: ${W.newBlockId}`];if(W.insertedBlock){let{blockType:H,content:J}=W.insertedBlock,B=J.length>200?`${J.slice(0,200)}...`:J;if(G.push(`Type: ${H}`),B)G.push(`Content: ${B}`)}let Y=E6(W.positionContext);if(Y)G.push(`Position: ${Y}`);return G.join(`
|
|
75
85
|
`)},getLogMessage:(W)=>{let G;if(W.parentBlockId)G=`in:${W.parentBlockId.slice(0,8)}`;else if(W.beforeBlockId)G=`before:${W.beforeBlockId.slice(0,8)}`;else if(W.afterBlockId)G=`after:${W.afterBlockId.slice(0,8)}`;else G="start";if(W.blocks&&W.blocks.length>0)return`${W.entityType}/${W.entityId.slice(0,8)} ${G} (batch: ${W.blocks.length} blocks)`;return`${W.entityType}/${W.entityId.slice(0,8)} ${G} (${W.blockType??"paragraph"})`}})}var VC=R.object({query:R.string().min(1).optional().describe("Search query keywords"),mode:R.enum(["library","blocks"]).default("library").describe('Search mode: "library" returns unique entities (papers/docs), "blocks" returns block-level results'),scope:R.object({type:R.enum(["literature","document","record"]).optional().describe("Filter by entity type"),entityId:R.string().uuid().optional().describe("Search within specific entity (blocks mode only)")}).optional().describe("Optional scope to narrow search"),orgId:R.string().uuid().optional().describe("Organization ID - use the one from workspace context"),workspaceId:R.string().uuid().optional().describe("Filter by workspace ID"),spaceId:R.string().uuid().optional().describe("Filter by space ID"),limit:R.number().min(1).max(50).default(10).describe("Max results. Default: 10"),authorName:R.string().optional().describe('Filter by author name (partial match). Example: "Shen" finds papers by authors named Shen'),journalName:R.string().optional().describe('Filter by journal name (partial match). Example: "Nano Letters" finds papers from Nano Letters'),yearMin:R.number().int().min(1900).max(2100).optional().describe("Minimum publication year (inclusive)"),yearMax:R.number().int().min(1900).max(2100).optional().describe("Maximum publication year (inclusive)")});function AC(Q,X){if(Q>0){if(Q<0.5)return"high";if(Q<1.5)return"medium";return"low"}return X>0?"medium":"low"}var UC={name:"search",description:`Search across literature, documents, and records.
|
|
76
86
|
|
|
@@ -112,7 +122,7 @@ These filters can be combined with \`query\` to narrow content search results:
|
|
|
112
122
|
**Retrieval Hints:**
|
|
113
123
|
Library mode results include \`bestBlockId\` and smart \`retrievalHint\`:
|
|
114
124
|
- High relevance: Jump directly to the best block via \`blockIds=['bestBlockId']\`
|
|
115
|
-
- Medium/Low relevance: Start with \`overview=true\` to explore structure first`};function MD(Q,X){L1(Q,X,{definition:UC,schema:VC,createExecutor:(W)=>{return async(G)=>{let Y=G.mode??"library",H=await W.client.search({query:G.query,mode:Y,entityType:G.scope?.type,entityId:G.scope?.entityId,orgId:G.orgId,workspaceId:G.workspaceId,spaceId:G.spaceId,limit:G.limit??10,offset:0,authorName:G.authorName,yearMin:G.yearMin,yearMax:G.yearMax,journalName:G.journalName}),J=H.results??[];if(Y==="library"){let $=J.map((q)=>{let{bestMatch:z}=q,V=AC(z.rank,q.matchCount);return{entityType:q.entityType,entityId:q.entityId,entityTitle:q.entityTitle,matchCount:q.matchCount,bestBlockId:z.blockId,snippet:z.snippet,relevance:V,retrievalHint:z.blockId?{recommended:"blockIds",usage:`blockIds=['${z.blockId}']`}:{recommended:"overview",usage:"overview=true"}}});return{mode:"library",found:$.length,results:$,hasMore:H.hasMore}}let B=J.map(($)=>({entityType:$.entityType,entityId:$.entityId,entityTitle:$.entityTitle,blockId:"blockId"in $?$.blockId:"",snippet:"snippet"in $?$.snippet:"",relevance:"medium",retrievalHint:{recommended:"blockIds",usage:`blockIds=['${"blockId"in $?$.blockId:""}']`}}));return{mode:"blocks",found:B.length,results:B,hasMore:H.hasMore}}},formatOutput:(W)=>JSON.stringify(W,null,2),getLogMessage:(W)=>W.query?`"${W.query}"`:"metadata filters"})}var DC=R.object({entityType:R.enum(["document","record"]).describe('Entity type: "document" or "record"'),entityId:R.string().uuid().describe("Document or record ID"),blockId:R.string().describe("Block ID to edit"),oldText:R.string().describe("Exact text to find and replace (must match exactly)"),newText:R.string().describe("Text to replace with")}),KC={name:"str_replace_block",description:"Replace text content in a specific block. Works like Claude Code str_replace - find exact text and replace it. oldText must match exactly (case-sensitive). Use get_content first to see exact block content."};function LD(Q,X){L1(Q,X,{definition:KC,schema:DC,createExecutor:(W)=>{return async(G)=>{return await W.client.strReplaceBlock(G)}},formatOutput:(W)=>{if(!W.success)return`Replace failed: ${W.error}`;let G=[`Text replaced in block ${W.blockId
|
|
125
|
+
- Medium/Low relevance: Start with \`overview=true\` to explore structure first`};function MD(Q,X){L1(Q,X,{definition:UC,schema:VC,createExecutor:(W)=>{return async(G)=>{let Y=G.mode??"library",H=await W.client.search({query:G.query,mode:Y,entityType:G.scope?.type,entityId:G.scope?.entityId,orgId:G.orgId,workspaceId:G.workspaceId,spaceId:G.spaceId,limit:G.limit??10,offset:0,authorName:G.authorName,yearMin:G.yearMin,yearMax:G.yearMax,journalName:G.journalName}),J=H.results??[];if(Y==="library"){let $=J.map((q)=>{let{bestMatch:z}=q,V=AC(z.rank,q.matchCount);return{entityType:q.entityType,entityId:q.entityId,entityTitle:q.entityTitle,matchCount:q.matchCount,bestBlockId:z.blockId,snippet:z.snippet,relevance:V,retrievalHint:z.blockId?{recommended:"blockIds",usage:`blockIds=['${z.blockId}']`}:{recommended:"overview",usage:"overview=true"}}});return{mode:"library",found:$.length,results:$,hasMore:H.hasMore}}let B=J.map(($)=>({entityType:$.entityType,entityId:$.entityId,entityTitle:$.entityTitle,blockId:"blockId"in $?$.blockId:"",snippet:"snippet"in $?$.snippet:"",relevance:"medium",retrievalHint:{recommended:"blockIds",usage:`blockIds=['${"blockId"in $?$.blockId:""}']`}}));return{mode:"blocks",found:B.length,results:B,hasMore:H.hasMore}}},formatOutput:(W)=>JSON.stringify(W,null,2),getLogMessage:(W)=>W.query?`"${W.query}"`:"metadata filters"})}var DC=R.object({entityType:R.enum(["document","record"]).describe('Entity type: "document" or "record"'),entityId:R.string().uuid().describe("Document or record ID"),blockId:R.string().describe("Block ID to edit"),oldText:R.string().describe("Exact text to find and replace (must match exactly)"),newText:R.string().describe("Text to replace with")}),KC={name:"str_replace_block",description:"Replace text content in a specific block. Works like Claude Code str_replace - find exact text and replace it. oldText must match exactly (case-sensitive). Use get_content first to see exact block content. Content supports SURA markdown inline syntax: **bold**, *italic*, ~~strike~~, `code`, {u}underline{/u}, {color:red}text color{/color}, {bg:yellow}background{/bg}. Colors: default, gray, brown, red, orange, yellow, green, blue, purple, pink."};function LD(Q,X){L1(Q,X,{definition:KC,schema:DC,createExecutor:(W)=>{return async(G)=>{return await W.client.strReplaceBlock(G)}},formatOutput:(W)=>{if(!W.success)return`Replace failed: ${W.error}`;let G=[`Text replaced in block ${W.blockId}`];if(W.originalText&&W.updatedText)G.push(BD(W.originalText,W.updatedText));let Y=E6(W.positionContext);if(Y)G.push(`Position: ${Y}`);return G.join(`
|
|
116
126
|
|
|
117
127
|
`)},getLogMessage:(W)=>`${W.entityType}/${W.entityId.slice(0,8)} block ${W.blockId.slice(0,8)}`})}function wD(Q,X){X.log.info("Registering tools..."),MD(Q,X),zD(Q,X),LD(Q,X),KD(Q,X),qD(Q,X),JD(Q,X),VD(Q,X),X.log.info("All tools registered")}function MC(){let Q=process.argv.slice(2),X={};for(let W=0;W<Q.length;W++){let G=Q[W],Y=Q[W+1];if((G==="--api-key"||G==="-k")&&Y)X.apiKey=Y,W++;else if((G==="--api-url"||G==="-u")&&Y)X.apiUrl=Y,W++;else if(G==="--help"||G==="-h")console.error(`
|
|
118
128
|
SURA MCP Server - Search, read, and edit your research workspace
|