@sura_ai/mcp-server 0.2.4 → 0.2.5
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 +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -232,4 +232,4 @@ Library mode results include \`bestBlockId\` and smart \`retrievalHint\`:
|
|
|
232
232
|
${QI()}`),note:G.string().min(1).describe("REQUIRED rationale (§5.9c): a concise free-text justification for asserting this typed relation. Domain specificity lives here; the predicate stays universal. Stored in `relation_note`; the structural `role` is left untouched.")}),lu=ob.extend({note:G.string().optional()}),e0={name:"update_artifact_link_relation",description:["Set the TYPED, queryable SEMANTIC relation on an existing artifact ↔ source link (an `artifact_links` row) — the epistemic/methodological layer the structural roles (input/output/derived_from/referenced) cannot express.","Use this to record what a node/record actually *does* relative to a linked artifact: tests a hypothesis, supports/refutes a claim, replicates a prior run, supersedes/corrects an entity, uses a protocol, or characterizes a sample.","This is SEPARATE from `link_artifact_to_node` (which creates the row + sets the structural `role`). It keys on the join-row `artifactLinkId` and writes ONLY `relation_type`/`relation_note`; the structural `role` is never changed.","The eight predicates are deliberately tight and universal — pick the one whose argument structure matches; put domain specificity in the REQUIRED `note`, never by inventing a predicate (unknown predicates are rejected).","Predicates (disjoint from structural roles — NEVER pass a structural role here):",QI(),"Re-calling with the same `artifactLinkId` re-types the relation in place."].join(`
|
|
233
233
|
`)};var db=G.object({edgeId:G.string().uuid().optional().describe("OPTIONAL. Present → RE-TYPE mode: the mention already carries this `edgeId` prop (an already-promoted edge); the tool re-edits the typed metadata in place (DB-only, no document write). Absent → PROMOTION mode: the mention is currently untyped; the tool locates the mention inline in the source entity, mints a fresh `edgeId` into it (the durable anchor), then writes the typed edge. Promotion needs WebSocket config; re-type does not."),sourceEntityId:G.string().uuid().describe("UUID of the document/record the mention lives in (the edge subject)."),sourceEntityType:G.enum(["document","record"]).describe("Type of the source entity (document or record)."),targetEntityId:G.string().uuid().describe("UUID of the mentioned entity (the edge object)."),targetEntityType:G.enum(["literature","document","record","artifact","matrix"]).describe("Type of the mentioned (target) entity."),blockId:G.string().optional().describe("PROMOTION mode only. Optional block scope: when set, only that block is searched for the target mention; when omitted, the whole source entity body is searched. Pass this to disambiguate when the same entity is mentioned in multiple blocks (the tool returns an `ambiguous_mention` error telling you to.) Ignored in re-type mode."),occurrence:G.number().int().min(0).optional().describe("PROMOTION mode only. 0-based index among matching mentions within the search scope (default 0 = first match). Pass this to disambiguate when a single block contains multiple mentions of the same target entity (the tool returns an `ambiguous_mention` error telling you to). Ignored in re-type mode."),relationType:a0.describe(`The relation predicate. One of the eight ratified, disjoint-from-structural predicates:
|
|
234
234
|
${QI()}`),note:G.string().min(1).describe("REQUIRED rationale (§5.9c): a concise free-text justification for asserting this typed edge. Domain specificity lives here; the predicate stays universal."),direction:G.enum(["forward","inverse"]).describe("Reading orientation (§6.2). `forward` = subject → object (the source entity tests/uses/etc. the mentioned entity — the usual case). `inverse` = object → subject (e.g. the mentioned reviewer note *refutes* this document). Storage always keeps source = subject; this only flips the reading.")}),cu=db.extend({edgeId:G.string().uuid(),note:G.string().optional()}),s0={name:"update_edge",description:["Promote a plain @mention into a TYPED, queryable, convergence-preserved relationship edge — the epistemic/methodological layer the structural links (input/output/derived_from/referenced) cannot express.","Use this to record what a run/analysis/result actually *does* relative to another entity: tests a hypothesis, supports/refutes a claim, replicates a prior run, supersedes/corrects an entity, uses a protocol, or characterizes a sample.","The eight predicates are deliberately tight and universal — pick the one whose argument structure matches; put domain specificity in the REQUIRED `note`, never by inventing a predicate (unknown predicates are rejected).","Predicates (disjoint from structural roles — NEVER pass a structural role here):",QI(),"Two modes: (a) PROMOTION — omit `edgeId`; the tool finds the @mention of `targetEntity` inside `sourceEntity`, writes a durable edge anchor into the document, then types the edge. Disambiguate with `blockId` and/or `occurrence` if the tool reports `ambiguous_mention`. (b) RE-TYPE — pass the existing `edgeId` (an already-promoted mention) to re-edit the typed metadata in place. Either way, the metadata survives every document convergence."].join(`
|
|
235
|
-
`)};var mu=G.record(G.string(),G.union([G.string(),G.number(),G.boolean(),G.null()])).describe("Row match: every provided key/value must equal the row's current value. Matches all rows where the criteria hold (not just the first)."),ru=G.object({rowIndex:G.number().int().min(0).optional().describe("Target a single row by 0-based index in the current rows array."),rowMatch:mu.optional(),values:q1.describe("Partial row patch. **Keys MUST match `col.key` (the column id), NOT `col.label`.** Keys present here overwrite the matching rows' cells. Keys not in `values` retain their existing values. Set a key to null to clear a cell.")}).refine(($)=>{let I=$.rowIndex!==void 0,U=$.rowMatch!==void 0;return I!==U},{message:"Provide exactly one of `rowIndex` (absolute) or `rowMatch` (by column values).",path:["rowIndex"]}),S5=G.object({matrixId:G.string().uuid().describe("UUID of the target data_matrix."),updates:G.array(ru).min(1).describe("List of row patches. Each entry targets rows by `rowIndex` OR `rowMatch` and supplies a partial `values` patch."),version:G.number().int().min(0).describe("Current matrix version (optimistic locking). Must equal the server's stored version; otherwise returns a matrix_version_conflict error.")}),$D={name:"update_matrix_rows",description:["Patch cells in an existing data matrix. Each update targets rows by `rowIndex` (absolute 0-based) OR `rowMatch` (every provided column/value must equal the row's current cell); partial column updates are allowed.","**All row-keyed objects (`values`, `rowMatch`) MUST use `col.key` as the object key, NOT `col.label`.** Read the schema first via `get_content` on the owning entity — its matrix TOON shows `cols: key(Label,type[,unit])` and a `{key1,key2,...}` row header. Mismatched keys persist as opaque JSONB that the UI cannot render.","Match mode updates every row that satisfies the criteria — use it when the match is unique, or when you intend to update a whole group at once.","Bumps `version` on success; stale `version` returns a structured `matrix_version_conflict` error with the current server version so you can re-fetch and retry.","Set a `values` entry to null to clear a cell. Keys not present in `values` are untouched.","Only draft records are writable; completed/locked records return a `record_not_draft` error.",'**Stoichiometry matrices** (`kind=stoichiometry` in the matrix header): clearing a numeric cell to null re-enables client-side derivation via the chemistry identities (n = m/M, n = V·c, m = V·ρ·purity, n = stockMolarity·V, n = stockWtPercent·ρ_soln·V/M, n_i = equiv_i · n_limiting, equiv_i = n_i / n_limiting). Keys not in `values` stay untouched — use this to preserve the hidden `compoundId` link to a chemical artifact while patching other cells. Do not manually recompute derived quantities; write only measured or locked-in values. For aqueous stock solutions, set `stockMolarity` (mol/L) or `stockWtPercent` (0–100) rather than approximating via `purity` × `density`. The displayed `c` is computed against a per-row reference volume controlled by two hidden keys: `cBasis` (`null` | `"none"` | `"phase"` | `"total"` | `"manual"`; null = engine picks default by role+phase, "phase" = c relative to V_phase, "total" = c relative to V_total, "manual" = c relative to `cBasisManualVolume`, "none" = blank c) and `cBasisManualVolume` (mL, only used when cBasis="manual"). Leave both null unless the user explicitly set them.'].join(" ")};var j5=G.object({nodeId:G.string().uuid().describe("UUID of the existing procedure node to update."),label:G.string().min(1).optional().describe("New label (skip to keep existing)."),type:F1.optional().describe('New type (skip to keep existing). Changing type to "observation" forces copyable=false.'),copyable:G.boolean().optional().describe('Template-copyable flag. When the resulting type is "observation" this must be false (or omitted).'),analyticalData:G.array(E1).optional().describe("Replace the current `analyticalData` list with this one. Pass an empty array to clear it; omit to leave it untouched.")}).refine(($)=>{if($.type!=="observation")return!0;return $.copyable===void 0||$.copyable===!1},{message:'copyable must be false (or omitted) when type is "observation".',path:["copyable"]}).refine(($)=>$.label!==void 0||$.type!==void 0||$.copyable!==void 0||$.analyticalData!==void 0,{message:"Provide at least one field to update (label, type, copyable, analyticalData)."}),ID={name:"update_procedure_node",description:["Update non-structural fields of a procedure-tree node (label, type, copyable, analyticalData).","Structural changes (move / reorder) go through `reorder_procedure_nodes` — this tool never touches parentId or order.",'`type === "observation"` implies `copyable = false`; setting both to a conflicting combination is rejected.',"Passing an empty `analyticalData` array clears the file-ref list; omitting the field leaves it untouched.","Only draft records are writable; completed/locked records return a `record_not_draft` error."].join(" ")};var k5=[i0,g0,o0,d0,h0,K0,P0,T0,j0,k0,R0,S0,y0,x0,m0,F0,f0,ID,n0,Z0,v0,$D,E0,C0,r0,V0,l0,_0,u0,p0,c0,e0,s0,v5,b5,N5,M5,O5],nu=k5.map(($)=>$.name),iu=Object.fromEntries(k5.map(($)=>[$.name,$]));function P5($){return{content:[{type:"text",text:$}]}}function R5($){return{content:[{type:"text",text:$}],isError:!0}}function g($,I,U){let{definition:A,schema:D,createExecutor:w,formatOutput:b,formatError:N=(Q)=>Q.message,getLogMessage:O=(Q)=>JSON.stringify(Q).slice(0,100)}=U,X=w(I),W=D.shape;$.tool(A.name,A.description,W,async(Q)=>{let B=Q,Y=O(B);I.log.info(`${A.name}: ${Y}`);try{let J=await X(B),H=b(J,B);return I.log.info(`${A.name}: completed`),P5(H)}catch(J){let H=J instanceof Error?N(J,B):"Unknown error";return I.log.error(`${A.name} failed:`,J),R5(`${A.name} error: ${H}`)}})}function pb($,I,U){let{definition:A,schema:D,createExecutor:w,formatSuccess:b,formatNotFound:N=(B)=>JSON.stringify({found:!1,error:B.error??"Not found"}),formatError:O=(B)=>B.message,getLogMessage:X=(B)=>JSON.stringify(B).slice(0,100)}=U,W=w(I),Q=D.shape;$.tool(A.name,A.description,Q,async(B)=>{let Y=B,J=X(Y);I.log.info(`${A.name}: ${J}`);try{let H=await W(Y);if(!H.found)return I.log.info(`${A.name}: not found`),{content:[{type:"text",text:N(H,Y)}],isError:!0};return I.log.info(`${A.name}: found`),P5(b(H,Y))}catch(H){let V=H instanceof Error?O(H,Y):"Unknown error";return I.log.error(`${A.name} failed:`,H),R5(`${A.name} error: ${V}`)}})}function BF($,I){g($,I,{definition:v0,schema:B7,createExecutor:(U)=>{return async(A)=>{return await U.client.appendMatrixRows(A)}},formatOutput:o7,getLogMessage:(U)=>`Appending ${U.rows.length} row(s) to matrix ${U.matrixId.slice(0,8)}`})}function JF($,I){g($,I,{definition:V0,schema:J7,createExecutor:(U)=>{return async(A)=>{return await U.client.attachMatrix(A)}},formatOutput:e7,getLogMessage:(U)=>{let A=U.nodeRef?` + node ${U.nodeRef.slice(0,8)}`:"";return`Attaching matrix ${U.matrixId.slice(0,8)} → ${U.entityType}:${U.entityId.slice(0,8)}${A}`}})}function HF($,I){g($,I,{definition:F0,schema:H7,createExecutor:(U)=>{return async(A)=>{return await U.client.buildProcedureTree(A)}},formatOutput:i7,getLogMessage:(U)=>`${U.mode==="replace"?"REPLACE":"append"} procedure tree for record ${U.recordId.slice(0,8)}: ${U.nodes.length} node(s)`})}function LF($,I){g($,I,{definition:S0,schema:z7,createExecutor:(U)=>{return async(A)=>{return await U.client.createArtifact(A)}},formatOutput:u7,getLogMessage:(U)=>`Creating ${U.artifactType} "${U.name.slice(0,30)}"`})}function zF($,I){g($,I,{definition:j0,schema:M7,createExecutor:(U)=>{return async(A)=>{return await U.client.createDocument(A)}},formatOutput:R7,getLogMessage:(U)=>`Creating document: "${U.title.slice(0,30)}${U.title.length>30?"...":""}"`})}function MF($,I){g($,I,{definition:k0,schema:K7,createExecutor:(U)=>{return async(A)=>{return U.client.createLiterature(A)}},formatOutput:T7,getLogMessage:(U)=>`Importing literature: "${U.title.slice(0,30)}${U.title.length>30?"...":""}"${U.doi?` (DOI: ${U.doi})`:""}`})}function KF($,I){g($,I,{definition:P0,schema:v7,createExecutor:(U)=>{return async(A)=>{return await U.client.createMatrixFromArtifact(A)}},formatOutput:C7,getLogMessage:(U)=>`Deriving matrix from artifact ${U.artifactId.slice(0,8)}`})}function vF($,I){g($,I,{definition:R0,schema:V7,createExecutor:(U)=>{return async(A)=>{return await U.client.createRecord(A)}},formatOutput:h7,getLogMessage:(U)=>`Creating record: "${U.title.slice(0,30)}${U.title.length>30?"...":""}"${U.initialTree?` + ${U.initialTree.length} node(s)`:""}`})}function VF($,I){g($,I,{definition:T0,schema:rb,createExecutor:(U)=>{return async(A)=>{return await U.client.deleteBlock(A)}},formatOutput:x7,getLogMessage:(U)=>{if(U.blockIds&&U.blockIds.length>0)return`${U.entityType}/${U.entityId.slice(0,8)} batch delete ${U.blockIds.length} blocks`;return`${U.entityType}/${U.entityId.slice(0,8)} block ${U.blockId?.slice(0,8)??"unknown"}`}})}function qF($,I){g($,I,{definition:_0,schema:q7,createExecutor:(U)=>{return async(A)=>{return await U.client.deleteMatrix(A)}},formatOutput:a7,getLogMessage:(U)=>`Deleting matrix ${U.matrixId.slice(0,8)} (+ block)`})}function FF($,I){g($,I,{definition:C0,schema:F7,createExecutor:(U)=>{return async(A)=>{return await U.client.deleteMatrixRows(A)}},formatOutput:p7,getLogMessage:(U)=>{return`Deleting rows (${U.rowIndices?`${U.rowIndices.length} index(es)`:"match"}) from matrix ${U.matrixId.slice(0,8)}`}})}function EF($,I){g($,I,{definition:Z0,schema:E7,createExecutor:(U)=>{return async(A)=>{return await U.client.deleteProcedureNode(A)}},formatOutput:n7,getLogMessage:(U)=>`Deleting procedure node ${U.nodeId.slice(0,8)} (cascade)`})}function SF($,I){pb($,I,{definition:g0,schema:X5,createExecutor:(U)=>{return async(A)=>{return U.client.getContent(A)}},formatSuccess:P7,formatNotFound:(U)=>JSON.stringify({found:!1,error:U.error??"Entity not found"}),getLogMessage:(U)=>{let A=U.blockIds?`blocks:${U.blockIds.length}`:U.segment?`segment:"${U.segment}"`:U.from_section&&U.to_section?`range:"${U.from_section}"-"${U.to_section}"`:U.node?`node:"${U.node}"${U.depth!==void 0?`,depth=${U.depth}`:""}`:U.section?`section:"${U.section}"${U.depth!==void 0?`,depth=${U.depth}`:""}`:U.refs?`refs:${U.refs.length}`:"overview";return`${U.entityId.slice(0,8)}... (${A})`}})}function jF($,I){g($,I,{definition:x0,schema:W5,createExecutor:(U)=>{return async(A)=>{if(U.workspaceContext&&!A.forceRefresh)return U.workspaceContext;let D=await U.client.getWorkspaceContext();return U.workspaceContext=D,D}},formatOutput:S7,getLogMessage:(U)=>U.forceRefresh?"force refresh":"cached"})}function kF($,I){g($,I,{definition:h0,schema:ib,createExecutor:(U)=>{return async(A)=>{return await U.client.insertBlock(A)}},formatOutput:g7,getLogMessage:(U)=>{let A;if(U.parentBlockId)A=`in:${U.parentBlockId.slice(0,8)}`;else if(U.beforeBlockId)A=`before:${U.beforeBlockId.slice(0,8)}`;else if(U.afterBlockId)A=`after:${U.afterBlockId.slice(0,8)}`;else A="start";if(U.blocks&&U.blocks.length>0)return`${U.entityType}/${U.entityId.slice(0,8)} ${A} (batch: ${U.blocks.length} blocks)`;return`${U.entityType}/${U.entityId.slice(0,8)} ${A} (${U.blockType??"paragraph"})`}})}function PF($,I){g($,I,{definition:K0,schema:Y7,createExecutor:(U)=>{return async(A)=>{return await U.client.insertMatrix(A)}},formatOutput:(U)=>_7(U),getLogMessage:(U)=>`"${U.label.slice(0,30)}${U.label.length>30?"...":""}"`})}function RF($,I){g($,I,{definition:f0,schema:G5,createExecutor:(U)=>{return async(A)=>{return await U.client.insertProcedureNode(A)}},formatOutput:f7,getLogMessage:(U)=>`Inserting procedure node "${U.label.slice(0,30)}" into record ${U.recordId.slice(0,8)}`})}function TF($,I){g($,I,{definition:y0,schema:Q5,createExecutor:(U)=>{return async(A)=>{return await U.client.instantiateArtifactTemplate(A)}},formatOutput:c7,getLogMessage:(U)=>`Instantiating template ${U.templateId.slice(0,8)} → "${U.name}"`})}function _F($,I){g($,I,{definition:u0,schema:Y5,createExecutor:(U)=>{return async(A)=>{return await U.client.linkArtifactToNode(A)}},formatOutput:$5,getLogMessage:(U)=>`Linking artifact ${U.artifactId.slice(0,8)} → node ${U.nodeId.slice(0,8)} (${U.role})`})}function CF($,I){g($,I,{definition:l0,schema:B5,createExecutor:(U)=>{return async(A)=>{return await U.client.listMatrixReferences(A)}},formatOutput:s7,getLogMessage:(U)=>`Listing references for matrix ${U.matrixId.slice(0,8)}`})}function ZF($,I){g($,I,{definition:c0,schema:J5,createExecutor:(U)=>{return async(A)=>{return await U.client.listNodeArtifactLinks(A)}},formatOutput:A5,getLogMessage:(U)=>`Listing artifact links for node ${U.nodeId.slice(0,8)}`})}function gF($,I){g($,I,{definition:m0,schema:H5,createExecutor:(U)=>{return async(A)=>{return await U.client.listProcedureNodes(A)}},formatOutput:w5,getLogMessage:(U)=>`Listing procedure nodes for record ${U.recordId.slice(0,8)}`})}function xF($,I){g($,I,{definition:r0,schema:L5,createExecutor:(U)=>{return async(A)=>{return await U.client.rebindMatrixToNode(A)}},formatOutput:t7,getLogMessage:(U)=>{let A=U.nodeRef?U.nodeRef.slice(0,8):"(body)";return`Rebinding matrix ${U.matrixId.slice(0,8)} → ${A}`}})}function hF($,I){g($,I,{definition:n0,schema:z5,createExecutor:(U)=>{return async(A)=>{return await U.client.reorderProcedureNodes(A)}},formatOutput:r7,getLogMessage:(U)=>`Reordering ${U.moves.length} procedure node(s) in record ${U.recordId.slice(0,8)}`})}function ou($,I){if($>0){if($<0.5)return"high";if($<1.5)return"medium";return"low"}return I>0?"medium":"low"}function fF($,I){g($,I,{definition:i0,schema:K5,createExecutor:(U)=>{return async(A)=>{let D=A.mode??"library",w=A.limit??10;if(A.scope?.type==="artifact"&&D==="library"&&A.workspaceId){let X=await U.client.searchArtifacts({workspaceId:A.workspaceId,query:A.query,artifactType:A.artifactType,artifactStatus:A.artifactStatus,limit:w}),W=X.results.map((Q)=>{let B=Q.description?Q.description.length>100?`${Q.description.slice(0,97)}...`:Q.description:`${Q.artifactType}, ${Q.status}`;return{entityType:"artifact",entityId:Q.id,entityTitle:Q.name,matchCount:1,bestBlockId:"",snippet:B,relevance:"high",retrievalHint:{recommended:"overview",usage:`get_content(entityId="${Q.id}")`}}});return{mode:"library",found:W.length,results:W,hasMore:X.hasMore}}let b=await U.client.search({query:A.query,mode:D,entityType:A.scope?.type,entityId:A.scope?.entityId,orgId:A.orgId,workspaceId:A.workspaceId,spaceId:A.spaceId,limit:w,offset:0,authorName:A.authorName,yearMin:A.yearMin,yearMax:A.yearMax,journalName:A.journalName}),N=b.results??[];if(D==="library"){let X=N.map((W)=>{let{bestMatch:Q}=W,B=ou(Q.rank,W.matchCount),Y={entityType:W.entityType,entityId:W.entityId,entityTitle:W.entityTitle,matchCount:W.matchCount,bestBlockId:Q.blockId,snippet:Q.snippet,relevance:B,tags:W.tags,retrievalHint:Q.blockId?{recommended:"blockIds",usage:`blockIds=['${Q.blockId}']`}:{recommended:"overview",usage:"overview=true"}};if(W.literatureMetadata)Y.literatureMetadata=W.literatureMetadata;if(W.creatorId)Y.creatorId=W.creatorId;if(W.creatorName)Y.creatorName=W.creatorName;return Y});return{mode:"library",found:X.length,results:X,hasMore:b.hasMore}}let O=N.map((X)=>{let W={entityType:X.entityType,entityId:X.entityId,entityTitle:X.entityTitle,blockId:"blockId"in X?X.blockId:"",snippet:"snippet"in X?X.snippet:"",relevance:"medium",retrievalHint:{recommended:"blockIds",usage:`blockIds=['${"blockId"in X?X.blockId:""}']`}},Q=X.creatorId,B=X.creatorName;if(Q)W.creatorId=Q;if(B)W.creatorName=B;return W});return{mode:"blocks",found:O.length,results:O,hasMore:b.hasMore}}},formatOutput:(U)=>j7(U),getLogMessage:(U)=>U.query?`"${U.query}"`:"metadata filters"})}function yF($,I){pb($,I,{definition:o0,schema:V5,createExecutor:(U)=>{return async(A)=>{return U.client.situate(A)}},formatSuccess:k7,formatNotFound:(U)=>JSON.stringify({found:!1,error:U.error??"Entity not found"}),getLogMessage:(U)=>`${U.entityId.slice(0,8)}... (depth ${U.depth??2})`})}function uF($,I){g($,I,{definition:d0,schema:q5,createExecutor:(U)=>{return async(A)=>{return await U.client.strReplaceBlock(A)}},formatOutput:Z7,getLogMessage:(U)=>`${U.entityType}/${U.entityId.slice(0,8)} block ${U.blockId.slice(0,8)}`})}function lF($,I){g($,I,{definition:p0,schema:F5,createExecutor:(U)=>{return async(A)=>{return await U.client.unlinkArtifactFromNode(A)}},formatOutput:D5,getLogMessage:(U)=>`Unlinking artifact link ${U.linkId.slice(0,8)}`})}function cF($,I){g($,I,{definition:E0,schema:L7,createExecutor:(U)=>{return async(A)=>{return await U.client.updateArtifact(A)}},formatOutput:m7,getLogMessage:(U)=>`Updating artifact ${U.id.slice(0,8)}`})}function mF($,I){g($,I,{definition:e0,schema:ob,createExecutor:(U)=>{return async(A)=>{return await U.client.updateArtifactLinkRelation(A)}},formatOutput:U5,getLogMessage:(U)=>`Typing artifact link ${U.artifactLinkId.slice(0,8)} as "${U.relationType}"`})}function rF($,I){g($,I,{definition:s0,schema:db,createExecutor:(U)=>{return async(A)=>{return await U.client.updateEdge(A)}},formatOutput:I5,getLogMessage:(U)=>U.edgeId?`Re-typing edge ${U.edgeId.slice(0,8)} as "${U.relationType}" (${U.direction})`:`Promoting @mention → "${U.relationType}" edge (${U.direction})`})}function nF($,I){g($,I,{definition:$D,schema:S5,createExecutor:(U)=>{return async(A)=>{return await U.client.updateMatrixRows(A)}},formatOutput:d7,getLogMessage:(U)=>`Updating ${U.updates.length} row target(s) in matrix ${U.matrixId.slice(0,8)}`})}function iF($,I){g($,I,{definition:ID,schema:j5,createExecutor:(U)=>{return async(A)=>{return await U.client.updateProcedureNode(A)}},formatOutput:y7,getLogMessage:(U)=>`Updating procedure node ${U.nodeId.slice(0,8)}`})}function oF($,I){I.log.info("Registering tools..."),fF($,I),SF($,I),yF($,I),uF($,I),kF($,I),PF($,I),KF($,I),VF($,I),zF($,I),MF($,I),vF($,I),jF($,I),gF($,I),HF($,I),RF($,I),iF($,I),hF($,I),EF($,I),BF($,I),nF($,I),FF($,I),xF($,I),qF($,I),JF($,I),CF($,I),LF($,I),cF($,I),TF($,I),_F($,I),lF($,I),ZF($,I),mF($,I),rF($,I),I.log.info("All tools registered")}function du(){let $=process.argv.slice(2),I={};for(let U=0;U<$.length;U++){let A=$[U],D=$[U+1];if((A==="--api-key"||A==="-k")&&D)I.apiKey=D,U++;else if((A==="--api-url"||A==="-u")&&D)I.apiUrl=D,U++;else if(A==="--help"||A==="-h")process.exit(0)}return I}A4.info("Starting SURA MCP Server...");var dF=du(),pF=dF.apiKey??process.env.SURA_API_KEY,pu=dF.apiUrl??process.env.SURA_API_URL??"https://api.sura.science";if(!pF)A4.error("Missing API key. Set SURA_API_KEY environment variable or use --api-key flag."),A4.error("Get your API key at https://app.sura.science/settings/api-keys"),process.exit(1);var tu=await UV({apiUrl:pu,apiKey:pF}),tF=new pW({name:"sura",version:"0.1.0"});oF(tF,tu);var aF=new aW,eF=async($)=>{A4.info(`Received ${$}, shutting down...`),await aF.close(),process.exit(0)};process.on("SIGTERM",()=>eF("SIGTERM"));process.on("SIGINT",()=>eF("SIGINT"));process.on("uncaughtException",($)=>{A4.error("Uncaught exception:",$)});process.on("unhandledRejection",($)=>{A4.error("Unhandled rejection:",$)});A4.info("Connecting stdio transport...");await tF.connect(aF);A4.info("SURA MCP Server ready");
|
|
235
|
+
`)};var mu=G.record(G.string(),G.union([G.string(),G.number(),G.boolean(),G.null()])).describe("Row match: every provided key/value must equal the row's current value. Matches all rows where the criteria hold (not just the first)."),ru=G.object({rowIndex:G.number().int().min(0).optional().describe("Target a single row by 0-based index in the current rows array."),rowMatch:mu.optional(),values:q1.describe("Partial row patch. **Keys MUST match `col.key` (the column id), NOT `col.label`.** Keys present here overwrite the matching rows' cells. Keys not in `values` retain their existing values. Set a key to null to clear a cell.")}).refine(($)=>{let I=$.rowIndex!==void 0,U=$.rowMatch!==void 0;return I!==U},{message:"Provide exactly one of `rowIndex` (absolute) or `rowMatch` (by column values).",path:["rowIndex"]}),S5=G.object({matrixId:G.string().uuid().describe("UUID of the target data_matrix."),updates:G.array(ru).min(1).describe("List of row patches. Each entry targets rows by `rowIndex` OR `rowMatch` and supplies a partial `values` patch."),version:G.number().int().min(0).describe("Current matrix version (optimistic locking). Must equal the server's stored version; otherwise returns a matrix_version_conflict error.")}),$D={name:"update_matrix_rows",description:["Patch cells in an existing data matrix. Each update targets rows by `rowIndex` (absolute 0-based) OR `rowMatch` (every provided column/value must equal the row's current cell); partial column updates are allowed.","**All row-keyed objects (`values`, `rowMatch`) MUST use `col.key` as the object key, NOT `col.label`.** Read the schema first via `get_content` on the owning entity — its matrix TOON shows `cols: key(Label,type[,unit])` and a `{key1,key2,...}` row header. Mismatched keys persist as opaque JSONB that the UI cannot render.","Match mode updates every row that satisfies the criteria — use it when the match is unique, or when you intend to update a whole group at once.","Bumps `version` on success; stale `version` returns a structured `matrix_version_conflict` error with the current server version so you can re-fetch and retry.","Set a `values` entry to null to clear a cell. Keys not present in `values` are untouched.","Only draft records are writable; completed/locked records return a `record_not_draft` error.",'**Stoichiometry matrices** (`kind=stoichiometry` in the matrix header): clearing a numeric cell to null re-enables client-side derivation via the chemistry identities (n = m/M, n = V·c, m = V·ρ·purity, n = stockMolarity·V, n = stockWtPercent·ρ_soln·V/M, n_i = equiv_i · n_limiting, equiv_i = n_i / n_limiting). Keys not in `values` stay untouched — use this to preserve the hidden `compoundId` link to a chemical artifact while patching other cells. Do not manually recompute derived quantities; write only measured or locked-in values. For aqueous stock solutions, set `stockMolarity` (mol/L) or `stockWtPercent` (0–100) rather than approximating via `purity` × `density`. The displayed `c` is computed against a per-row reference volume controlled by two hidden keys: `cBasis` (`null` | `"none"` | `"phase"` | `"total"` | `"manual"`; null = engine picks default by role+phase, "phase" = c relative to V_phase, "total" = c relative to V_total, "manual" = c relative to `cBasisManualVolume`, "none" = blank c) and `cBasisManualVolume` (mL, only used when cBasis="manual"). Leave both null unless the user explicitly set them.'].join(" ")};var j5=G.object({nodeId:G.string().uuid().describe("UUID of the existing procedure node to update."),label:G.string().min(1).optional().describe("New label (skip to keep existing)."),type:F1.optional().describe('New type (skip to keep existing). Changing type to "observation" forces copyable=false.'),copyable:G.boolean().optional().describe('Template-copyable flag. When the resulting type is "observation" this must be false (or omitted).'),analyticalData:G.array(E1).optional().describe("Replace the current `analyticalData` list with this one. Pass an empty array to clear it; omit to leave it untouched.")}).refine(($)=>{if($.type!=="observation")return!0;return $.copyable===void 0||$.copyable===!1},{message:'copyable must be false (or omitted) when type is "observation".',path:["copyable"]}).refine(($)=>$.label!==void 0||$.type!==void 0||$.copyable!==void 0||$.analyticalData!==void 0,{message:"Provide at least one field to update (label, type, copyable, analyticalData)."}),ID={name:"update_procedure_node",description:["Update non-structural fields of a procedure-tree node (label, type, copyable, analyticalData).","Structural changes (move / reorder) go through `reorder_procedure_nodes` — this tool never touches parentId or order.",'`type === "observation"` implies `copyable = false`; setting both to a conflicting combination is rejected.',"Passing an empty `analyticalData` array clears the file-ref list; omitting the field leaves it untouched.","Only draft records are writable; completed/locked records return a `record_not_draft` error."].join(" ")};var k5=[i0,g0,o0,d0,h0,K0,P0,T0,j0,k0,R0,S0,y0,x0,m0,F0,f0,ID,n0,Z0,v0,$D,E0,C0,r0,V0,l0,_0,u0,p0,c0,e0,s0,v5,b5,N5,M5,O5],nu=k5.map(($)=>$.name),iu=Object.fromEntries(k5.map(($)=>[$.name,$]));function P5($){return{content:[{type:"text",text:$}]}}function R5($){return{content:[{type:"text",text:$}],isError:!0}}function g($,I,U){let{definition:A,schema:D,createExecutor:w,formatOutput:b,formatError:N=(Q)=>Q.message,getLogMessage:O=(Q)=>JSON.stringify(Q).slice(0,100)}=U,X=w(I),W=D.shape;$.tool(A.name,A.description,W,async(Q)=>{let B=Q,Y=O(B);I.log.info(`${A.name}: ${Y}`);try{let J=await X(B),H=b(J,B);return I.log.info(`${A.name}: completed`),P5(H)}catch(J){let H=J instanceof Error?N(J,B):"Unknown error";return I.log.error(`${A.name} failed:`,J),R5(`${A.name} error: ${H}`)}})}function pb($,I,U){let{definition:A,schema:D,createExecutor:w,formatSuccess:b,formatNotFound:N=(B)=>JSON.stringify({found:!1,error:B.error??"Not found"}),formatError:O=(B)=>B.message,getLogMessage:X=(B)=>JSON.stringify(B).slice(0,100)}=U,W=w(I),Q=D.shape;$.tool(A.name,A.description,Q,async(B)=>{let Y=B,J=X(Y);I.log.info(`${A.name}: ${J}`);try{let H=await W(Y);if(!H.found)return I.log.info(`${A.name}: not found`),{content:[{type:"text",text:N(H,Y)}],isError:!0};return I.log.info(`${A.name}: found`),P5(b(H,Y))}catch(H){let V=H instanceof Error?O(H,Y):"Unknown error";return I.log.error(`${A.name} failed:`,H),R5(`${A.name} error: ${V}`)}})}function BF($,I){g($,I,{definition:v0,schema:B7,createExecutor:(U)=>{return async(A)=>{return await U.client.appendMatrixRows(A)}},formatOutput:o7,getLogMessage:(U)=>`Appending ${U.rows.length} row(s) to matrix ${U.matrixId.slice(0,8)}`})}function JF($,I){g($,I,{definition:V0,schema:J7,createExecutor:(U)=>{return async(A)=>{return await U.client.attachMatrix(A)}},formatOutput:e7,getLogMessage:(U)=>{let A=U.nodeRef?` + node ${U.nodeRef.slice(0,8)}`:"";return`Attaching matrix ${U.matrixId.slice(0,8)} → ${U.entityType}:${U.entityId.slice(0,8)}${A}`}})}function HF($,I){g($,I,{definition:F0,schema:H7,createExecutor:(U)=>{return async(A)=>{return await U.client.buildProcedureTree(A)}},formatOutput:i7,getLogMessage:(U)=>`${U.mode==="replace"?"REPLACE":"append"} procedure tree for record ${U.recordId.slice(0,8)}: ${U.nodes.length} node(s)`})}function LF($,I){g($,I,{definition:S0,schema:z7,createExecutor:(U)=>{return async(A)=>{return await U.client.createArtifact(A)}},formatOutput:u7,getLogMessage:(U)=>`Creating ${U.artifactType} "${U.name.slice(0,30)}"`})}function zF($,I){g($,I,{definition:j0,schema:M7,createExecutor:(U)=>{return async(A)=>{return await U.client.createDocument(A)}},formatOutput:R7,getLogMessage:(U)=>`Creating document: "${U.title.slice(0,30)}${U.title.length>30?"...":""}"`})}function MF($,I){g($,I,{definition:k0,schema:K7,createExecutor:(U)=>{return async(A)=>{return U.client.createLiterature(A)}},formatOutput:T7,getLogMessage:(U)=>`Importing literature: "${U.title.slice(0,30)}${U.title.length>30?"...":""}"${U.doi?` (DOI: ${U.doi})`:""}`})}function KF($,I){g($,I,{definition:P0,schema:v7,createExecutor:(U)=>{return async(A)=>{return await U.client.createMatrixFromArtifact(A)}},formatOutput:C7,getLogMessage:(U)=>`Deriving matrix from artifact ${U.artifactId.slice(0,8)}`})}function vF($,I){g($,I,{definition:R0,schema:V7,createExecutor:(U)=>{return async(A)=>{return await U.client.createRecord(A)}},formatOutput:h7,getLogMessage:(U)=>`Creating record: "${U.title.slice(0,30)}${U.title.length>30?"...":""}"${U.initialTree?` + ${U.initialTree.length} node(s)`:""}`})}function VF($,I){g($,I,{definition:T0,schema:rb,createExecutor:(U)=>{return async(A)=>{return await U.client.deleteBlock(A)}},formatOutput:x7,getLogMessage:(U)=>{if(U.blockIds&&U.blockIds.length>0)return`${U.entityType}/${U.entityId.slice(0,8)} batch delete ${U.blockIds.length} blocks`;return`${U.entityType}/${U.entityId.slice(0,8)} block ${U.blockId?.slice(0,8)??"unknown"}`}})}function qF($,I){g($,I,{definition:_0,schema:q7,createExecutor:(U)=>{return async(A)=>{return await U.client.deleteMatrix(A)}},formatOutput:a7,getLogMessage:(U)=>`Deleting matrix ${U.matrixId.slice(0,8)} (+ block)`})}function FF($,I){g($,I,{definition:C0,schema:F7,createExecutor:(U)=>{return async(A)=>{return await U.client.deleteMatrixRows(A)}},formatOutput:p7,getLogMessage:(U)=>{return`Deleting rows (${U.rowIndices?`${U.rowIndices.length} index(es)`:"match"}) from matrix ${U.matrixId.slice(0,8)}`}})}function EF($,I){g($,I,{definition:Z0,schema:E7,createExecutor:(U)=>{return async(A)=>{return await U.client.deleteProcedureNode(A)}},formatOutput:n7,getLogMessage:(U)=>`Deleting procedure node ${U.nodeId.slice(0,8)} (cascade)`})}function SF($,I){pb($,I,{definition:g0,schema:X5,createExecutor:(U)=>{return async(A)=>{return U.client.getContent(A)}},formatSuccess:P7,formatNotFound:(U)=>JSON.stringify({found:!1,error:U.error??"Entity not found"}),getLogMessage:(U)=>{let A=U.blockIds?`blocks:${U.blockIds.length}`:U.segment?`segment:"${U.segment}"`:U.from_section&&U.to_section?`range:"${U.from_section}"-"${U.to_section}"`:U.node?`node:"${U.node}"${U.depth!==void 0?`,depth=${U.depth}`:""}`:U.section?`section:"${U.section}"${U.depth!==void 0?`,depth=${U.depth}`:""}`:U.refs?`refs:${U.refs.length}`:"overview";return`${U.entityId.slice(0,8)}... (${A})`}})}function jF($,I){g($,I,{definition:x0,schema:W5,createExecutor:(U)=>{return async(A)=>{if(U.workspaceContext&&!A.forceRefresh)return U.workspaceContext;let D=await U.client.getWorkspaceContext();return U.workspaceContext=D,D}},formatOutput:S7,getLogMessage:(U)=>U.forceRefresh?"force refresh":"cached"})}function kF($,I){g($,I,{definition:h0,schema:ib,createExecutor:(U)=>{return async(A)=>{return await U.client.insertBlock(A)}},formatOutput:g7,getLogMessage:(U)=>{let A;if(U.parentBlockId)A=`in:${U.parentBlockId.slice(0,8)}`;else if(U.beforeBlockId)A=`before:${U.beforeBlockId.slice(0,8)}`;else if(U.afterBlockId)A=`after:${U.afterBlockId.slice(0,8)}`;else A="start";if(U.blocks&&U.blocks.length>0)return`${U.entityType}/${U.entityId.slice(0,8)} ${A} (batch: ${U.blocks.length} blocks)`;return`${U.entityType}/${U.entityId.slice(0,8)} ${A} (${U.blockType??"paragraph"})`}})}function PF($,I){g($,I,{definition:K0,schema:Y7,createExecutor:(U)=>{return async(A)=>{return await U.client.insertMatrix(A)}},formatOutput:(U)=>_7(U),getLogMessage:(U)=>`"${U.label.slice(0,30)}${U.label.length>30?"...":""}"`})}function RF($,I){g($,I,{definition:f0,schema:G5,createExecutor:(U)=>{return async(A)=>{return await U.client.insertProcedureNode(A)}},formatOutput:f7,getLogMessage:(U)=>`Inserting procedure node "${U.label.slice(0,30)}" into record ${U.recordId.slice(0,8)}`})}function TF($,I){g($,I,{definition:y0,schema:Q5,createExecutor:(U)=>{return async(A)=>{return await U.client.instantiateArtifactTemplate(A)}},formatOutput:c7,getLogMessage:(U)=>`Instantiating template ${U.templateId.slice(0,8)} → "${U.name}"`})}function _F($,I){g($,I,{definition:u0,schema:Y5,createExecutor:(U)=>{return async(A)=>{return await U.client.linkArtifactToNode(A)}},formatOutput:$5,getLogMessage:(U)=>`Linking artifact ${U.artifactId.slice(0,8)} → node ${U.nodeId.slice(0,8)} (${U.role})`})}function CF($,I){g($,I,{definition:l0,schema:B5,createExecutor:(U)=>{return async(A)=>{return await U.client.listMatrixReferences(A)}},formatOutput:s7,getLogMessage:(U)=>`Listing references for matrix ${U.matrixId.slice(0,8)}`})}function ZF($,I){g($,I,{definition:c0,schema:J5,createExecutor:(U)=>{return async(A)=>{return await U.client.listNodeArtifactLinks(A)}},formatOutput:A5,getLogMessage:(U)=>`Listing artifact links for node ${U.nodeId.slice(0,8)}`})}function gF($,I){g($,I,{definition:m0,schema:H5,createExecutor:(U)=>{return async(A)=>{return await U.client.listProcedureNodes(A)}},formatOutput:w5,getLogMessage:(U)=>`Listing procedure nodes for record ${U.recordId.slice(0,8)}`})}function xF($,I){g($,I,{definition:r0,schema:L5,createExecutor:(U)=>{return async(A)=>{return await U.client.rebindMatrixToNode(A)}},formatOutput:t7,getLogMessage:(U)=>{let A=U.nodeRef?U.nodeRef.slice(0,8):"(body)";return`Rebinding matrix ${U.matrixId.slice(0,8)} → ${A}`}})}function hF($,I){g($,I,{definition:n0,schema:z5,createExecutor:(U)=>{return async(A)=>{return await U.client.reorderProcedureNodes(A)}},formatOutput:r7,getLogMessage:(U)=>`Reordering ${U.moves.length} procedure node(s) in record ${U.recordId.slice(0,8)}`})}function ou($,I){if($>0){if($<0.5)return"high";if($<1.5)return"medium";return"low"}return I>0?"medium":"low"}function fF($,I){g($,I,{definition:i0,schema:K5,createExecutor:(U)=>{return async(A)=>{let D=A.mode??"library",w=A.limit??10;if(A.scope?.type==="artifact"&&D==="library"&&A.workspaceId){let X=await U.client.searchArtifacts({workspaceId:A.workspaceId,query:A.query,artifactType:A.artifactType,artifactStatus:A.artifactStatus,limit:w}),W=X.results.map((Q)=>{let B=Q.description?Q.description.length>100?`${Q.description.slice(0,97)}...`:Q.description:`${Q.artifactType}, ${Q.status}`;return{entityType:"artifact",entityId:Q.id,entityTitle:Q.name,matchCount:1,bestBlockId:"",snippet:B,relevance:"high",retrievalHint:{recommended:"overview",usage:`get_content(entityId="${Q.id}")`}}});return{mode:"library",found:W.length,results:W,hasMore:X.hasMore}}let b=await U.client.search({query:A.query,mode:D,entityType:A.scope?.type,entityId:A.scope?.entityId,orgId:A.orgId,workspaceId:A.workspaceId,spaceId:A.spaceId,limit:w,offset:0,authorName:A.authorName,yearMin:A.yearMin,yearMax:A.yearMax,journalName:A.journalName}),N=b.results??[];if(D==="library"){let X=N.map((W)=>{let{bestMatch:Q}=W,B=ou(Q.rank,W.matchCount),Y={entityType:W.entityType,entityId:W.entityId,entityTitle:W.entityTitle,matchCount:W.matchCount,bestBlockId:Q.blockId,snippet:Q.snippet,relevance:B,tags:W.tags,retrievalHint:Q.blockId?{recommended:"blockIds",usage:`blockIds=['${Q.blockId}']`}:{recommended:"overview",usage:"overview=true"}};if(W.literatureMetadata)Y.literatureMetadata=W.literatureMetadata;if(W.creatorId)Y.creatorId=W.creatorId;if(W.creatorName)Y.creatorName=W.creatorName;if(W.updatedAt instanceof Date)Y.updatedAt=W.updatedAt.toISOString().slice(0,10);else if(typeof W.updatedAt==="string")Y.updatedAt=W.updatedAt.slice(0,10);return Y});return{mode:"library",found:X.length,results:X,hasMore:b.hasMore}}let O=N.map((X)=>{let W={entityType:X.entityType,entityId:X.entityId,entityTitle:X.entityTitle,blockId:"blockId"in X?X.blockId:"",snippet:"snippet"in X?X.snippet:"",relevance:"medium",retrievalHint:{recommended:"blockIds",usage:`blockIds=['${"blockId"in X?X.blockId:""}']`}},Q=X.creatorId,B=X.creatorName;if(Q)W.creatorId=Q;if(B)W.creatorName=B;return W});return{mode:"blocks",found:O.length,results:O,hasMore:b.hasMore}}},formatOutput:(U)=>j7(U),getLogMessage:(U)=>U.query?`"${U.query}"`:"metadata filters"})}function yF($,I){pb($,I,{definition:o0,schema:V5,createExecutor:(U)=>{return async(A)=>{return U.client.situate(A)}},formatSuccess:k7,formatNotFound:(U)=>JSON.stringify({found:!1,error:U.error??"Entity not found"}),getLogMessage:(U)=>`${U.entityId.slice(0,8)}... (depth ${U.depth??2})`})}function uF($,I){g($,I,{definition:d0,schema:q5,createExecutor:(U)=>{return async(A)=>{return await U.client.strReplaceBlock(A)}},formatOutput:Z7,getLogMessage:(U)=>`${U.entityType}/${U.entityId.slice(0,8)} block ${U.blockId.slice(0,8)}`})}function lF($,I){g($,I,{definition:p0,schema:F5,createExecutor:(U)=>{return async(A)=>{return await U.client.unlinkArtifactFromNode(A)}},formatOutput:D5,getLogMessage:(U)=>`Unlinking artifact link ${U.linkId.slice(0,8)}`})}function cF($,I){g($,I,{definition:E0,schema:L7,createExecutor:(U)=>{return async(A)=>{return await U.client.updateArtifact(A)}},formatOutput:m7,getLogMessage:(U)=>`Updating artifact ${U.id.slice(0,8)}`})}function mF($,I){g($,I,{definition:e0,schema:ob,createExecutor:(U)=>{return async(A)=>{return await U.client.updateArtifactLinkRelation(A)}},formatOutput:U5,getLogMessage:(U)=>`Typing artifact link ${U.artifactLinkId.slice(0,8)} as "${U.relationType}"`})}function rF($,I){g($,I,{definition:s0,schema:db,createExecutor:(U)=>{return async(A)=>{return await U.client.updateEdge(A)}},formatOutput:I5,getLogMessage:(U)=>U.edgeId?`Re-typing edge ${U.edgeId.slice(0,8)} as "${U.relationType}" (${U.direction})`:`Promoting @mention → "${U.relationType}" edge (${U.direction})`})}function nF($,I){g($,I,{definition:$D,schema:S5,createExecutor:(U)=>{return async(A)=>{return await U.client.updateMatrixRows(A)}},formatOutput:d7,getLogMessage:(U)=>`Updating ${U.updates.length} row target(s) in matrix ${U.matrixId.slice(0,8)}`})}function iF($,I){g($,I,{definition:ID,schema:j5,createExecutor:(U)=>{return async(A)=>{return await U.client.updateProcedureNode(A)}},formatOutput:y7,getLogMessage:(U)=>`Updating procedure node ${U.nodeId.slice(0,8)}`})}function oF($,I){I.log.info("Registering tools..."),fF($,I),SF($,I),yF($,I),uF($,I),kF($,I),PF($,I),KF($,I),VF($,I),zF($,I),MF($,I),vF($,I),jF($,I),gF($,I),HF($,I),RF($,I),iF($,I),hF($,I),EF($,I),BF($,I),nF($,I),FF($,I),xF($,I),qF($,I),JF($,I),CF($,I),LF($,I),cF($,I),TF($,I),_F($,I),lF($,I),ZF($,I),mF($,I),rF($,I),I.log.info("All tools registered")}function du(){let $=process.argv.slice(2),I={};for(let U=0;U<$.length;U++){let A=$[U],D=$[U+1];if((A==="--api-key"||A==="-k")&&D)I.apiKey=D,U++;else if((A==="--api-url"||A==="-u")&&D)I.apiUrl=D,U++;else if(A==="--help"||A==="-h")process.exit(0)}return I}A4.info("Starting SURA MCP Server...");var dF=du(),pF=dF.apiKey??process.env.SURA_API_KEY,pu=dF.apiUrl??process.env.SURA_API_URL??"https://api.sura.science";if(!pF)A4.error("Missing API key. Set SURA_API_KEY environment variable or use --api-key flag."),A4.error("Get your API key at https://app.sura.science/settings/api-keys"),process.exit(1);var tu=await UV({apiUrl:pu,apiKey:pF}),tF=new pW({name:"sura",version:"0.1.0"});oF(tF,tu);var aF=new aW,eF=async($)=>{A4.info(`Received ${$}, shutting down...`),await aF.close(),process.exit(0)};process.on("SIGTERM",()=>eF("SIGTERM"));process.on("SIGINT",()=>eF("SIGINT"));process.on("uncaughtException",($)=>{A4.error("Uncaught exception:",$)});process.on("unhandledRejection",($)=>{A4.error("Unhandled rejection:",$)});A4.info("Connecting stdio transport...");await tF.connect(aF);A4.info("SURA MCP Server ready");
|