@sura_ai/mcp-server 0.1.20 → 0.1.21
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 +6 -4
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -60,9 +60,9 @@ ${N}
|
|
|
60
60
|
+++ after
|
|
61
61
|
${A}`}function q3($){let X=[];X.push(`[workspace context | default org:${$.defaults.orgId}${$.defaults.workspaceId?` ws:${$.defaults.workspaceId}`:""}]`);let W=0,Q=[];for(let G of $.orgs)for(let Y of G.workspaces)if(Y.spaces.length===0)Q.push(c1([G.name,G.id,Y.name,Y.id,Y.type,"","",""])),W++;else for(let U of Y.spaces)Q.push(c1([G.name,G.id,Y.name,Y.id,Y.type,U.name,U.id,U.type])),W++;return X.push(`{org,orgId,workspace,wsId,wsType,space,spaceId,spaceType}[${W}]:`),X.push(...Q),X.join(`
|
|
62
62
|
`)}function L3($){let{mode:X,found:W,hasMore:Q}=$;if(W===0)return`[results:0 found, ${X}]
|
|
63
|
-
No results.`;let G=[X,...Q?["hasMore"]:[]].join(", "),Y=[`[results:${W} found, ${G}]`];if(X==="library"){let U=$.results,J=U.some((z)=>z.literatureMetadata),H=J?"{type,title,id,relevance,doi,firstAuthor,year,journal,snippet}":"{type,title,id,relevance,snippet}";Y.push(`${H}[${U.length}]:`);for(let z of U){let B=z.bestSnippet??z.snippet??"",D=B.length>120?`${B.slice(0,117)}...`:B;if(J){let
|
|
63
|
+
No results.`;let G=[X,...Q?["hasMore"]:[]].join(", "),Y=[`[results:${W} found, ${G}]`];if(X==="library"){let U=$.results,J=U.some((z)=>z.literatureMetadata),H=J?"{type,title,id,relevance,tags,doi,firstAuthor,year,journal,snippet}":"{type,title,id,relevance,tags,snippet}";Y.push(`${H}[${U.length}]:`);for(let z of U){let B=z.bestSnippet??z.snippet??"",D=B.length>120?`${B.slice(0,117)}...`:B,w=z.tags?.join(" | ")??"";if(J){let N=z.literatureMetadata;Y.push(c1([z.entityType,z.entityTitle,z.entityId,z.relevance,w,N?.doi??"",N?.firstAuthor??"",N?.year??"",N?.journal??"",D]))}else Y.push(c1([z.entityType,z.entityTitle,z.entityId,z.relevance,w,D]))}}else{let U=$.results;Y.push(`{type,title,entityId,blockId,snippet}[${U.length}]:`);for(let J of U){let H=J.bestSnippet??J.snippet??"",z=H.length>120?`${H.slice(0,117)}...`:H;Y.push(c1([J.entityType,J.entityTitle,J.entityId,J.blockId,z]))}}return Y.join(`
|
|
64
64
|
`)}function pv($){if($.length===0)return"";let X=[`[toc:${$.length} sections]`,`{title,level,tokens,ownTokens,blockId}[${$.length}]:`];for(let W of $)X.push(c1([W.title,W.level,W.estimatedTokens??0,W.ownTokens??0,W.blockId]));return X.join(`
|
|
65
|
-
`)}function rv($,X){return`${{literature:"lit",document:"doc",record:"rec",artifact:"art"}[$]??$.slice(0,3)}-${X.slice(0,8)}`}function I3($){let X=[];if(X.push(`**"${$.entityTitle}"** - ${$.entityType}`),$.bibliographic){let W=$.bibliographic,Q=[];if(W.authors?.length)Q.push(W.authors.length<=3?W.authors.join(", "):`${W.authors[0]} et al.`);if(W.journal)Q.push(W.journal);if(W.volume){let G=W.volume;if(W.issue)G+=`(${W.issue})`;if(W.pages)G+=`, ${W.pages}`;Q.push(G)}if(W.year)Q.push(String(W.year));if(Q.length>0)X.push(Q.join(", "));if(W.doi)X.push(`DOI: ${W.doi}`);if(W.pmid)X.push(`PMID: ${W.pmid}`);if(W.arxivId)X.push(`arXiv: ${W.arxivId}`)}if($.error)return X.push(""),X.push(`**Error:** ${$.error}`),X.join(`
|
|
65
|
+
`)}function rv($,X){return`${{literature:"lit",document:"doc",record:"rec",artifact:"art"}[$]??$.slice(0,3)}-${X.slice(0,8)}`}function I3($){let X=[];if(X.push(`**"${$.entityTitle}"** - ${$.entityType}`),$.bibliographic){let W=$.bibliographic,Q=[];if(W.authors?.length)Q.push(W.authors.length<=3?W.authors.join(", "):`${W.authors[0]} et al.`);if(W.journal)Q.push(W.journal);if(W.volume){let G=W.volume;if(W.issue)G+=`(${W.issue})`;if(W.pages)G+=`, ${W.pages}`;Q.push(G)}if(W.year)Q.push(String(W.year));if(Q.length>0)X.push(Q.join(", "));if(W.doi)X.push(`DOI: ${W.doi}`);if(W.pmid)X.push(`PMID: ${W.pmid}`);if(W.arxivId)X.push(`arXiv: ${W.arxivId}`);if(W.tags&&W.tags.length>0)X.push(`Tags: ${W.tags.join(", ")}`)}if($.error)return X.push(""),X.push(`**Error:** ${$.error}`),X.join(`
|
|
66
66
|
`);if($.overview){if($.overview.wordCount)X.push(`*~${$.overview.wordCount} words*`);if(X.push(""),$.overview.abstract)X.push("**Preview:**"),X.push($.overview.abstract),X.push("");if($.overview.toc&&$.overview.toc.length>0)X.push("**Table of Contents:**"),X.push(pv($.overview.toc))}if($.procedureTree)X.push(""),X.push("**Procedure Tree:**"),X.push($.procedureTree);if($.connections&&$.connections.total>0){if(X.push(""),X.push(`**Connections** (${$.connections.total} edges):`),$.connections.outgoing.length>0){X.push(""),X.push("*Outgoing (this entity → others):*");for(let W of $.connections.outgoing){let Q=W.referenceType==="annotation"?"\uD83D\uDCDD":W.referenceType==="citation"?"\uD83D\uDCD6":"↗",G=W.entityTitle||W.entityId.slice(0,8),Y=rv(W.entityType,W.entityId);if(W.edgeText)X.push(` ${Q} → ${W.entityType}: ${G} (${Y})`),X.push(` "${W.edgeText}"`);else X.push(` ${Q} → ${W.entityType}: ${G} (${Y}, ${W.referenceType})`)}}if($.connections.incoming.length>0){X.push(""),X.push("*Incoming (others → this entity):*");for(let W of $.connections.incoming){let Q=W.referenceType==="annotation"?"\uD83D\uDCDD":W.referenceType==="citation"?"\uD83D\uDCD6":"↙",G=W.entityTitle||W.entityId.slice(0,8),Y=rv(W.entityType,W.entityId);if(W.edgeText)X.push(` ${Q} ← ${W.entityType}: ${G} (${Y})`),X.push(` "${W.edgeText}"`);else X.push(` ${Q} ← ${W.entityType}: ${G} (${Y}, ${W.referenceType})`)}}}if($.markdown){if(X.push(""),$.format==="interleaved")X.push("**Content (with block IDs for editing):**");else X.push("**Markdown Content:**");X.push(""),X.push($.markdown)}if($.sectionInfo){if(X.push(""),X.push(`*Section: ${$.sectionInfo.blockCount} blocks, ${$.sectionInfo.wordCount} words*`),$.sectionInfo.warning)X.push(`*Warning: ${$.sectionInfo.warning}*`)}if($.refs&&$.refs.length>0)X.push(""),X.push("**References:**"),X.push("```json"),X.push(JSON.stringify($.refs,null,2)),X.push("```");return X.join(`
|
|
67
67
|
`)}function V3($){if(!$.success)return`Failed to create document: ${$.error}`;return`Document created successfully.
|
|
68
68
|
Title: ${$.title}
|
|
@@ -116,7 +116,7 @@ Batch mode: provide blocks array for multiple blocks in one call (more efficient
|
|
|
116
116
|
- Add paragraph: \`insert_block(afterBlockId="...", content="New text")\`
|
|
117
117
|
- Add heading: \`insert_block(afterBlockId="...", blockType="heading", headingLevel=2, content="Methods")\`
|
|
118
118
|
- Add checklist: \`insert_block(afterBlockId="...", blockType="checkListItem", checked=false, content="Run analysis")\`
|
|
119
|
-
- Batch insert section: \`insert_block(afterBlockId="...", blocks=[{blockType:"heading", headingLevel:2, content:"Results"}, {blockType:"paragraph", content:"We observed..."}])\``};var S3=b.object({query:b.string().min(1).optional().describe("Search query keywords"),mode:b.enum(["library","blocks"]).default("library").describe('Search mode: "library" returns unique entities (papers/docs), "blocks" returns block-level results'),scope:b.object({type:b.enum(["literature","document","record","artifact"]).optional().describe("Filter by entity type"),entityId:b.string().uuid().optional().describe("Search within specific entity (blocks mode only)")}).optional().describe("Optional scope to narrow search"),orgId:b.string().uuid().optional().describe("Organization ID - use the one from workspace context"),workspaceId:b.string().uuid().optional().describe("Filter by workspace ID"),spaceId:b.string().uuid().optional().describe("Filter by space ID"),limit:b.number().min(1).max(50).default(10).describe("Max results. Default: 10"),authorName:b.string().optional().describe('Filter by author name (partial match). Example: "Shen" finds papers by authors named Shen'),journalName:b.string().optional().describe('Filter by journal name (partial match). Example: "Nano Letters" finds papers from Nano Letters'),yearMin:b.number().int().min(1900).max(2100).optional().describe("Minimum publication year (inclusive)"),yearMax:b.number().int().min(1900).max(2100).optional().describe("Maximum publication year (inclusive)"),artifactType:b.string().optional().describe('Filter by artifact type: "sample", "dataset", "protocol", "file", "equipment", "chemical", "model"'),artifactStatus:b.string().optional().describe('Filter by artifact status: "active", "depleted", "archived", "draft"')}),S9={name:"search",description:`Search across literature, documents, records, and artifacts.
|
|
119
|
+
- Batch insert section: \`insert_block(afterBlockId="...", blocks=[{blockType:"heading", headingLevel:2, content:"Results"}, {blockType:"paragraph", content:"We observed..."}])\``};var S3=b.object({query:b.string().min(1).optional().describe("Search query keywords"),mode:b.enum(["library","blocks"]).default("library").describe('Search mode: "library" returns unique entities (papers/docs), "blocks" returns block-level results'),scope:b.object({type:b.enum(["literature","document","record","artifact"]).optional().describe("Filter by entity type"),entityId:b.string().uuid().optional().describe("Search within specific entity (blocks mode only)")}).optional().describe("Optional scope to narrow search"),orgId:b.string().uuid().optional().describe("Organization ID - use the one from workspace context"),workspaceId:b.string().uuid().optional().describe("Filter by workspace ID"),spaceId:b.string().uuid().optional().describe("Filter by space ID"),limit:b.number().min(1).max(50).default(10).describe("Max results. Default: 10"),authorName:b.string().optional().describe('Filter by author name (partial match). Example: "Shen" finds papers by authors named Shen'),journalName:b.string().optional().describe('Filter by journal name (partial match). Example: "Nano Letters" finds papers from Nano Letters'),yearMin:b.number().int().min(1900).max(2100).optional().describe("Minimum publication year (inclusive)"),yearMax:b.number().int().min(1900).max(2100).optional().describe("Maximum publication year (inclusive)"),tags:b.array(b.string()).optional().describe("Filter by tags. Matches entities that have any of the provided tags."),artifactType:b.string().optional().describe('Filter by artifact type: "sample", "dataset", "protocol", "file", "equipment", "chemical", "model"'),artifactStatus:b.string().optional().describe('Filter by artifact status: "active", "depleted", "archived", "draft"')}),S9={name:"search",description:`Search across literature, documents, records, and artifacts.
|
|
120
120
|
|
|
121
121
|
**Modes:**
|
|
122
122
|
- \`library\` (default): Returns unique entities ranked by relevance. Use when browsing/discovering.
|
|
@@ -149,9 +149,11 @@ Batch mode: provide blocks array for multiple blocks in one call (more efficient
|
|
|
149
149
|
- \`authorName\`: Filter by author (partial match, e.g., "Shen" finds authors named Shen)
|
|
150
150
|
- \`journalName\`: Filter by journal (partial match)
|
|
151
151
|
- \`yearMin\`/\`yearMax\`: Filter by publication year range
|
|
152
|
+
- \`tags\`: Filter by document/record/literature tags
|
|
152
153
|
|
|
153
154
|
These filters can be combined with \`query\` to narrow content search results:
|
|
154
155
|
\`search(query="catalysis", authorName="Shen")\` -> Papers by Shen mentioning catalysis
|
|
156
|
+
\`search(workspaceId="...", tags=["teaching", "rag"])\` -> Tagged entities in that workspace
|
|
155
157
|
|
|
156
158
|
**Artifact Search:**
|
|
157
159
|
Search artifacts (samples, chemicals, equipment, etc.) by name and type/status:
|
|
@@ -163,4 +165,4 @@ Requires \`workspaceId\`. Returns artifact names, types, and retrieval hints.
|
|
|
163
165
|
**Retrieval Hints:**
|
|
164
166
|
Library mode results include \`bestBlockId\` and smart \`retrievalHint\`:
|
|
165
167
|
- High relevance: Jump directly to the best block via \`blockIds=['bestBlockId']\`
|
|
166
|
-
- Medium/Low relevance: Start with \`overview=true\` to explore structure first`};var j3=b.object({entityType:m1.describe('Entity type: "document" or "record"'),entityId:b.string().uuid().describe("Document or record ID"),blockId:b.string().describe("Block ID to edit"),oldText:b.string().describe("Exact text to find and replace (must match exactly)"),newText:b.string().describe("Text to replace with")}),j9={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."};var R3=[S9,M9,j9,E9,F9,b9,K9,v9],Fl=R3.map(($)=>$.name),Ml=Object.fromEntries(R3.map(($)=>[$.name,$]));function k3($){return{content:[{type:"text",text:$}]}}function P3($){return{content:[{type:"text",text:$}],isError:!0}}function A6($,X,W){let{definition:Q,schema:G,createExecutor:Y,formatOutput:U,formatError:J=(D)=>D.message,getLogMessage:H=(D)=>JSON.stringify(D).slice(0,100)}=W,z=Y(X),B=G.shape;$.tool(Q.name,Q.description,B,async(D)=>{let w=D,N=H(w);X.log.info(`${Q.name}: ${N}`);try{let A=await z(w),q=U(A,w);return X.log.info(`${Q.name}: completed`),k3(q)}catch(A){let q=A instanceof Error?J(A,w):"Unknown error";return X.log.error(`${Q.name} failed:`,A),P3(`${Q.name} error: ${q}`)}})}function dv($,X,W){let{definition:Q,schema:G,createExecutor:Y,formatSuccess:U,formatNotFound:J=(w)=>JSON.stringify({found:!1,error:w.error??"Not found"}),formatError:H=(w)=>w.message,getLogMessage:z=(w)=>JSON.stringify(w).slice(0,100)}=W,B=Y(X),D=G.shape;$.tool(Q.name,Q.description,D,async(w)=>{let N=w,A=z(N);X.log.info(`${Q.name}: ${A}`);try{let q=await B(N);if(!q.found)return X.log.info(`${Q.name}: not found`),{content:[{type:"text",text:J(q,N)}],isError:!0};return X.log.info(`${Q.name}: found`),k3(U(q,N))}catch(q){let M=q instanceof Error?H(q,N):"Unknown error";return X.log.error(`${Q.name} failed:`,q),P3(`${Q.name} error: ${M}`)}})}function tv($,X){A6($,X,{definition:b9,schema:O3,createExecutor:(W)=>{return async(Q)=>{return await W.client.createDocument(Q)}},formatOutput:V3,getLogMessage:(W)=>`Creating document: "${W.title.slice(0,30)}${W.title.length>30?"...":""}"`})}function av($,X){A6($,X,{definition:K9,schema:A3,createExecutor:(W)=>{return async(Q)=>{return W.client.createLiterature(Q)}},formatOutput:b3,getLogMessage:(W)=>`Importing literature: "${W.title.slice(0,30)}${W.title.length>30?"...":""}"${W.doi?` (DOI: ${W.doi})`:""}`})}function ev($,X){A6($,X,{definition:F9,schema:SY,createExecutor:(W)=>{return async(Q)=>{return await W.client.deleteBlock(Q)}},formatOutput:M3,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"}`}})}function sv($,X){dv($,X,{definition:M9,schema:v3,createExecutor:(W)=>{return async(Q)=>{return W.client.getContent(Q)}},formatSuccess:I3,formatNotFound:(W)=>JSON.stringify({found:!1,error:W.error??"Entity not found"}),getLogMessage:(W)=>{let Q=W.blockIds?`blocks:${W.blockIds.length}`:W.from_section&&W.to_section?`range:"${W.from_section}"-"${W.to_section}"`:W.node?`node:"${W.node}"${W.depth!==void 0?`,depth=${W.depth}`:""}`: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)}... (${Q})`}})}function $E($,X){A6($,X,{definition:v9,schema:E3,createExecutor:(W)=>{return async(Q)=>{if(W.workspaceContext&&!Q.forceRefresh)return W.workspaceContext;let G=await W.client.getWorkspaceContext();return W.workspaceContext=G,G}},formatOutput:q3,getLogMessage:(W)=>W.forceRefresh?"force refresh":"cached"})}function XE($,X){A6($,X,{definition:E9,schema:RY,createExecutor:(W)=>{return async(Q)=>{return await W.client.insertBlock(Q)}},formatOutput:F3,getLogMessage:(W)=>{let Q;if(W.parentBlockId)Q=`in:${W.parentBlockId.slice(0,8)}`;else if(W.beforeBlockId)Q=`before:${W.beforeBlockId.slice(0,8)}`;else if(W.afterBlockId)Q=`after:${W.afterBlockId.slice(0,8)}`;else Q="start";if(W.blocks&&W.blocks.length>0)return`${W.entityType}/${W.entityId.slice(0,8)} ${Q} (batch: ${W.blocks.length} blocks)`;return`${W.entityType}/${W.entityId.slice(0,8)} ${Q} (${W.blockType??"paragraph"})`}})}function vl($,X){if($>0){if($<0.5)return"high";if($<1.5)return"medium";return"low"}return X>0?"medium":"low"}function WE($,X){A6($,X,{definition:S9,schema:S3,createExecutor:(W)=>{return async(Q)=>{let G=Q.mode??"library",Y=Q.limit??10;if(Q.scope?.type==="artifact"&&G==="library"&&Q.workspaceId){let z=await W.client.searchArtifacts({workspaceId:Q.workspaceId,query:Q.query,artifactType:Q.artifactType,artifactStatus:Q.artifactStatus,limit:Y}),B=z.results.map((D)=>{let w=D.description?D.description.length>100?`${D.description.slice(0,97)}...`:D.description:`${D.artifactType}, ${D.status}`;return{entityType:"artifact",entityId:D.id,entityTitle:D.name,matchCount:1,bestBlockId:"",snippet:w,relevance:"high",retrievalHint:{recommended:"overview",usage:`get_content(entityId="${D.id}")`}}});return{mode:"library",found:B.length,results:B,hasMore:z.hasMore}}let U=await W.client.search({query:Q.query,mode:G,entityType:Q.scope?.type,entityId:Q.scope?.entityId,orgId:Q.orgId,workspaceId:Q.workspaceId,spaceId:Q.spaceId,limit:Y,offset:0,authorName:Q.authorName,yearMin:Q.yearMin,yearMax:Q.yearMax,journalName:Q.journalName}),J=U.results??[];if(G==="library"){let z=J.map((B)=>{let{bestMatch:D}=B,w=vl(D.rank,B.matchCount),N={entityType:B.entityType,entityId:B.entityId,entityTitle:B.entityTitle,matchCount:B.matchCount,bestBlockId:D.blockId,snippet:D.snippet,relevance:w,retrievalHint:D.blockId?{recommended:"blockIds",usage:`blockIds=['${D.blockId}']`}:{recommended:"overview",usage:"overview=true"}};if(B.literatureMetadata)N.literatureMetadata=B.literatureMetadata;return N});return{mode:"library",found:z.length,results:z,hasMore:U.hasMore}}let H=J.map((z)=>({entityType:z.entityType,entityId:z.entityId,entityTitle:z.entityTitle,blockId:"blockId"in z?z.blockId:"",snippet:"snippet"in z?z.snippet:"",relevance:"medium",retrievalHint:{recommended:"blockIds",usage:`blockIds=['${"blockId"in z?z.blockId:""}']`}}));return{mode:"blocks",found:H.length,results:H,hasMore:U.hasMore}}},formatOutput:(W)=>L3(W),getLogMessage:(W)=>W.query?`"${W.query}"`:"metadata filters"})}function GE($,X){A6($,X,{definition:j9,schema:j3,createExecutor:(W)=>{return async(Q)=>{return await W.client.strReplaceBlock(Q)}},formatOutput:K3,getLogMessage:(W)=>`${W.entityType}/${W.entityId.slice(0,8)} block ${W.blockId.slice(0,8)}`})}function QE($,X){X.log.info("Registering tools..."),WE($,X),sv($,X),GE($,X),XE($,X),ev($,X),tv($,X),av($,X),$E($,X),X.log.info("All tools registered")}function El(){let $=process.argv.slice(2),X={};for(let W=0;W<$.length;W++){let Q=$[W],G=$[W+1];if((Q==="--api-key"||Q==="-k")&&G)X.apiKey=G,W++;else if((Q==="--api-url"||Q==="-u")&&G)X.apiUrl=G,W++;else if(Q==="--help"||Q==="-h")process.exit(0)}return X}R4.info("Starting SURA MCP Server...");var YE=El(),UE=YE.apiKey??process.env.SURA_API_KEY,Sl=YE.apiUrl??process.env.SURA_API_URL??"https://api.sura.science";if(!UE)R4.error("Missing API key. Set SURA_API_KEY environment variable or use --api-key flag."),R4.error("Get your API key at https://app.sura.science/settings/api-keys"),process.exit(1);var jl=await pF({apiUrl:Sl,apiKey:UE}),JE=new tH({name:"sura",version:"0.1.0"});QE(JE,jl);var HE=new eH,zE=async($)=>{R4.info(`Received ${$}, shutting down...`),await HE.close(),process.exit(0)};process.on("SIGTERM",()=>zE("SIGTERM"));process.on("SIGINT",()=>zE("SIGINT"));process.on("uncaughtException",($)=>{R4.error("Uncaught exception:",$)});process.on("unhandledRejection",($)=>{R4.error("Unhandled rejection:",$)});R4.info("Connecting stdio transport...");await JE.connect(HE);R4.info("SURA MCP Server ready");
|
|
168
|
+
- Medium/Low relevance: Start with \`overview=true\` to explore structure first`};var j3=b.object({entityType:m1.describe('Entity type: "document" or "record"'),entityId:b.string().uuid().describe("Document or record ID"),blockId:b.string().describe("Block ID to edit"),oldText:b.string().describe("Exact text to find and replace (must match exactly)"),newText:b.string().describe("Text to replace with")}),j9={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."};var R3=[S9,M9,j9,E9,F9,b9,K9,v9],Fl=R3.map(($)=>$.name),Ml=Object.fromEntries(R3.map(($)=>[$.name,$]));function k3($){return{content:[{type:"text",text:$}]}}function P3($){return{content:[{type:"text",text:$}],isError:!0}}function A6($,X,W){let{definition:Q,schema:G,createExecutor:Y,formatOutput:U,formatError:J=(D)=>D.message,getLogMessage:H=(D)=>JSON.stringify(D).slice(0,100)}=W,z=Y(X),B=G.shape;$.tool(Q.name,Q.description,B,async(D)=>{let w=D,N=H(w);X.log.info(`${Q.name}: ${N}`);try{let A=await z(w),q=U(A,w);return X.log.info(`${Q.name}: completed`),k3(q)}catch(A){let q=A instanceof Error?J(A,w):"Unknown error";return X.log.error(`${Q.name} failed:`,A),P3(`${Q.name} error: ${q}`)}})}function dv($,X,W){let{definition:Q,schema:G,createExecutor:Y,formatSuccess:U,formatNotFound:J=(w)=>JSON.stringify({found:!1,error:w.error??"Not found"}),formatError:H=(w)=>w.message,getLogMessage:z=(w)=>JSON.stringify(w).slice(0,100)}=W,B=Y(X),D=G.shape;$.tool(Q.name,Q.description,D,async(w)=>{let N=w,A=z(N);X.log.info(`${Q.name}: ${A}`);try{let q=await B(N);if(!q.found)return X.log.info(`${Q.name}: not found`),{content:[{type:"text",text:J(q,N)}],isError:!0};return X.log.info(`${Q.name}: found`),k3(U(q,N))}catch(q){let M=q instanceof Error?H(q,N):"Unknown error";return X.log.error(`${Q.name} failed:`,q),P3(`${Q.name} error: ${M}`)}})}function tv($,X){A6($,X,{definition:b9,schema:O3,createExecutor:(W)=>{return async(Q)=>{return await W.client.createDocument(Q)}},formatOutput:V3,getLogMessage:(W)=>`Creating document: "${W.title.slice(0,30)}${W.title.length>30?"...":""}"`})}function av($,X){A6($,X,{definition:K9,schema:A3,createExecutor:(W)=>{return async(Q)=>{return W.client.createLiterature(Q)}},formatOutput:b3,getLogMessage:(W)=>`Importing literature: "${W.title.slice(0,30)}${W.title.length>30?"...":""}"${W.doi?` (DOI: ${W.doi})`:""}`})}function ev($,X){A6($,X,{definition:F9,schema:SY,createExecutor:(W)=>{return async(Q)=>{return await W.client.deleteBlock(Q)}},formatOutput:M3,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"}`}})}function sv($,X){dv($,X,{definition:M9,schema:v3,createExecutor:(W)=>{return async(Q)=>{return W.client.getContent(Q)}},formatSuccess:I3,formatNotFound:(W)=>JSON.stringify({found:!1,error:W.error??"Entity not found"}),getLogMessage:(W)=>{let Q=W.blockIds?`blocks:${W.blockIds.length}`:W.from_section&&W.to_section?`range:"${W.from_section}"-"${W.to_section}"`:W.node?`node:"${W.node}"${W.depth!==void 0?`,depth=${W.depth}`:""}`: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)}... (${Q})`}})}function $E($,X){A6($,X,{definition:v9,schema:E3,createExecutor:(W)=>{return async(Q)=>{if(W.workspaceContext&&!Q.forceRefresh)return W.workspaceContext;let G=await W.client.getWorkspaceContext();return W.workspaceContext=G,G}},formatOutput:q3,getLogMessage:(W)=>W.forceRefresh?"force refresh":"cached"})}function XE($,X){A6($,X,{definition:E9,schema:RY,createExecutor:(W)=>{return async(Q)=>{return await W.client.insertBlock(Q)}},formatOutput:F3,getLogMessage:(W)=>{let Q;if(W.parentBlockId)Q=`in:${W.parentBlockId.slice(0,8)}`;else if(W.beforeBlockId)Q=`before:${W.beforeBlockId.slice(0,8)}`;else if(W.afterBlockId)Q=`after:${W.afterBlockId.slice(0,8)}`;else Q="start";if(W.blocks&&W.blocks.length>0)return`${W.entityType}/${W.entityId.slice(0,8)} ${Q} (batch: ${W.blocks.length} blocks)`;return`${W.entityType}/${W.entityId.slice(0,8)} ${Q} (${W.blockType??"paragraph"})`}})}function vl($,X){if($>0){if($<0.5)return"high";if($<1.5)return"medium";return"low"}return X>0?"medium":"low"}function WE($,X){A6($,X,{definition:S9,schema:S3,createExecutor:(W)=>{return async(Q)=>{let G=Q.mode??"library",Y=Q.limit??10;if(Q.scope?.type==="artifact"&&G==="library"&&Q.workspaceId){let z=await W.client.searchArtifacts({workspaceId:Q.workspaceId,query:Q.query,artifactType:Q.artifactType,artifactStatus:Q.artifactStatus,limit:Y}),B=z.results.map((D)=>{let w=D.description?D.description.length>100?`${D.description.slice(0,97)}...`:D.description:`${D.artifactType}, ${D.status}`;return{entityType:"artifact",entityId:D.id,entityTitle:D.name,matchCount:1,bestBlockId:"",snippet:w,relevance:"high",retrievalHint:{recommended:"overview",usage:`get_content(entityId="${D.id}")`}}});return{mode:"library",found:B.length,results:B,hasMore:z.hasMore}}let U=await W.client.search({query:Q.query,mode:G,entityType:Q.scope?.type,entityId:Q.scope?.entityId,orgId:Q.orgId,workspaceId:Q.workspaceId,spaceId:Q.spaceId,limit:Y,offset:0,authorName:Q.authorName,yearMin:Q.yearMin,yearMax:Q.yearMax,journalName:Q.journalName,tags:Q.tags}),J=U.results??[];if(G==="library"){let z=J.map((B)=>{let{bestMatch:D}=B,w=vl(D.rank,B.matchCount),N={entityType:B.entityType,entityId:B.entityId,entityTitle:B.entityTitle,matchCount:B.matchCount,bestBlockId:D.blockId,snippet:D.snippet,relevance:w,tags:B.tags,retrievalHint:D.blockId?{recommended:"blockIds",usage:`blockIds=['${D.blockId}']`}:{recommended:"overview",usage:"overview=true"}};if(B.literatureMetadata)N.literatureMetadata=B.literatureMetadata;return N});return{mode:"library",found:z.length,results:z,hasMore:U.hasMore}}let H=J.map((z)=>({entityType:z.entityType,entityId:z.entityId,entityTitle:z.entityTitle,blockId:"blockId"in z?z.blockId:"",snippet:"snippet"in z?z.snippet:"",relevance:"medium",retrievalHint:{recommended:"blockIds",usage:`blockIds=['${"blockId"in z?z.blockId:""}']`}}));return{mode:"blocks",found:H.length,results:H,hasMore:U.hasMore}}},formatOutput:(W)=>L3(W),getLogMessage:(W)=>W.query?`"${W.query}"`:"metadata filters"})}function GE($,X){A6($,X,{definition:j9,schema:j3,createExecutor:(W)=>{return async(Q)=>{return await W.client.strReplaceBlock(Q)}},formatOutput:K3,getLogMessage:(W)=>`${W.entityType}/${W.entityId.slice(0,8)} block ${W.blockId.slice(0,8)}`})}function QE($,X){X.log.info("Registering tools..."),WE($,X),sv($,X),GE($,X),XE($,X),ev($,X),tv($,X),av($,X),$E($,X),X.log.info("All tools registered")}function El(){let $=process.argv.slice(2),X={};for(let W=0;W<$.length;W++){let Q=$[W],G=$[W+1];if((Q==="--api-key"||Q==="-k")&&G)X.apiKey=G,W++;else if((Q==="--api-url"||Q==="-u")&&G)X.apiUrl=G,W++;else if(Q==="--help"||Q==="-h")process.exit(0)}return X}R4.info("Starting SURA MCP Server...");var YE=El(),UE=YE.apiKey??process.env.SURA_API_KEY,Sl=YE.apiUrl??process.env.SURA_API_URL??"https://api.sura.science";if(!UE)R4.error("Missing API key. Set SURA_API_KEY environment variable or use --api-key flag."),R4.error("Get your API key at https://app.sura.science/settings/api-keys"),process.exit(1);var jl=await pF({apiUrl:Sl,apiKey:UE}),JE=new tH({name:"sura",version:"0.1.0"});QE(JE,jl);var HE=new eH,zE=async($)=>{R4.info(`Received ${$}, shutting down...`),await HE.close(),process.exit(0)};process.on("SIGTERM",()=>zE("SIGTERM"));process.on("SIGINT",()=>zE("SIGINT"));process.on("uncaughtException",($)=>{R4.error("Uncaught exception:",$)});process.on("unhandledRejection",($)=>{R4.error("Unhandled rejection:",$)});R4.info("Connecting stdio transport...");await JE.connect(HE);R4.info("SURA MCP Server ready");
|