seojeom-mcp 0.3.1 → 0.3.2
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/README.md +8 -5
- package/dist/standalone.js +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -11,7 +11,7 @@ Local-first MCP server for Claude and Codex.
|
|
|
11
11
|
```bash
|
|
12
12
|
claude mcp add -s local \
|
|
13
13
|
-e SEOJEOM_SHARED_REGISTRY_DIR=/mnt/c/Users/<you>/.seojeom/registry \
|
|
14
|
-
seojeom --
|
|
14
|
+
seojeom -- npm exec --yes --package=seojeom-mcp seojeom-mcp -- \
|
|
15
15
|
--router \
|
|
16
16
|
--host-kind auto \
|
|
17
17
|
--approval-mode prompt
|
|
@@ -25,13 +25,16 @@ Add this to `claude_desktop_config.json` and restart Claude Desktop:
|
|
|
25
25
|
{
|
|
26
26
|
"mcpServers": {
|
|
27
27
|
"seojeom": {
|
|
28
|
-
"command": "
|
|
28
|
+
"command": "npm",
|
|
29
29
|
"env": {
|
|
30
30
|
"SEOJEOM_SHARED_REGISTRY_DIR": "<shared-registry-dir>"
|
|
31
31
|
},
|
|
32
32
|
"args": [
|
|
33
|
-
"
|
|
33
|
+
"exec",
|
|
34
|
+
"--yes",
|
|
35
|
+
"--package=seojeom-mcp",
|
|
34
36
|
"seojeom-mcp",
|
|
37
|
+
"--",
|
|
35
38
|
"--router",
|
|
36
39
|
"--host-kind", "auto",
|
|
37
40
|
"--approval-mode", "prompt"
|
|
@@ -44,7 +47,7 @@ Add this to `claude_desktop_config.json` and restart Claude Desktop:
|
|
|
44
47
|
### Print the exact onboarding command first
|
|
45
48
|
|
|
46
49
|
```bash
|
|
47
|
-
|
|
50
|
+
npm exec --yes --package=seojeom-mcp seojeom-mcp -- --print-claude-onboarding
|
|
48
51
|
```
|
|
49
52
|
|
|
50
53
|
## What it provides
|
|
@@ -60,7 +63,7 @@ The exact tool surface is discovered at runtime through MCP `tools/list`.
|
|
|
60
63
|
## Runtime contract
|
|
61
64
|
|
|
62
65
|
- primary transport: `stdio`
|
|
63
|
-
- primary install path: `
|
|
66
|
+
- primary install path: `npm exec --yes --package=seojeom-mcp seojeom-mcp --`
|
|
64
67
|
- recommended mode: shared-registry router mode
|
|
65
68
|
- expected runtime: Node `>=20.20.0`
|
|
66
69
|
- public npm package shape: standalone stdio entrypoint only
|
package/dist/standalone.js
CHANGED
|
@@ -147,12 +147,12 @@ ${n}`.trim()}function M6(t){return t.replace(/```[\s\S]*?```/g," ").replace(/`([
|
|
|
147
147
|
`)}],structuredContent:{rows:n,totalMatched:o.length}}}),t.registerTool("seojeom_read_wiki",{title:"Read Wiki Page",description:"Read a single wiki page and optionally its section index.",inputSchema:{pageId:x.string().min(1),includeSections:x.boolean().optional()}},async({pageId:r,includeSections:o})=>{let n=e.localWikiStore?await e.localWikiStore.readPage(r):await e.apiBridge.getJson(He(e,`/wiki/${encodeURIComponent(r)}`)),i=o?e.localWikiStore?await e.localWikiStore.readSections(r):await e.apiBridge.getJson(He(e,`/wiki/${encodeURIComponent(r)}/sections`)):null,a=[`[wiki] ${n.title}`,`- id: ${n.id}`,`- slug: ${n.slug}`,`- path: ${n.canonicalPath??"-"}`,`- node: ${n.primaryNodeRef??"-"}`,`- tags: ${n.tags.length>0?n.tags.join(", "):"-"}`,"",n.bodyMarkdown];if(i){a.push(""),a.push(`[sections] ${i.sections.length}\uAC1C`);for(let s of i.sections.slice(0,20))a.push(`- ${s.headingPath} (${s.sectionKey})`)}return{content:[{type:"text",text:a.join(`
|
|
148
148
|
`)}],structuredContent:{page:n,sections:i?.sections??null}}}),t.registerTool("seojeom_write_wiki",{title:"Write Wiki Page",description:"Create or update a wiki page for the current project. Mutations always pass through the configured approval controller.",inputSchema:{mode:x.enum(["create","update"]),pageId:x.string().optional(),title:x.string().optional(),bodyMarkdown:x.string().optional(),category:x.string().nullable().optional(),noteClass:x.string().nullable().optional(),nodeType:x.string().nullable().optional(),slug:x.string().optional(),tags:x.array(x.string()).optional(),canonicalPath:x.string().nullable().optional(),primaryNodeRef:x.string().nullable().optional(),canonLevel:x.string().nullable().optional(),isStructured:x.boolean().optional(),rootKind:x.enum(["raw","wiki","schema"]).nullable().optional(),linkedEpisodeIds:x.array(x.string()).optional(),linkedCharacterIds:x.array(x.string()).optional(),graphEdges:x.unknown().optional(),timeline:x.unknown().optional(),baseVersion:x.number().int().optional(),sourceProposalSetId:x.string().nullable().optional(),snapshotSource:x.string().optional()}},async({mode:r,pageId:o,title:n,bodyMarkdown:i,category:a,noteClass:s,nodeType:c,slug:l,tags:u,canonicalPath:p,primaryNodeRef:d,canonLevel:f,isStructured:h,rootKind:m,linkedEpisodeIds:g,linkedCharacterIds:b,graphEdges:$,timeline:S,baseVersion:z,sourceProposalSetId:k,snapshotSource:J})=>{let ee=vh(n),qe=vh(o),ve=Fo(a),Te=Fo(s),Bt=Fo(c),vt=vh(l),Ke=Fo(p),Pt=Fo(d),Dt=Fo(f),pn=Pw(u),Go=Pw(g),Sl=Pw(b),Ho=Fo(k),Xn=vh(J);if(r==="create"){if(!ee)throw new Error("title is required for wiki create");if(ve==null&&Te==null)throw new Error("category or noteClass is required for wiki create")}if(r==="update"){if(!qe)throw new Error("pageId is required for wiki update");if(typeof i!="string")throw new Error("bodyMarkdown is required for wiki update")}let Bo=await e.approval.requestApproval({action:"wiki_write",toolName:"seojeom_write_wiki",title:r==="create"?ee??"new wiki page":qe??"wiki page",summary:r==="create"?ve??Te??"create wiki page":ee??"update wiki page",details:kW([`mode=${r}`,vt?`slug=${vt}`:null,ve!=null?`category=${ve}`:null,Te!=null?`noteClass=${Te}`:null])});if(!Bo.approved)return{content:[{type:"text",text:[`[wiki write approval] ${r==="create"?ee??"new wiki page":qe??"wiki page"}`,"- status: denied",`- reason: ${Bo.reason??"approval denied"}`].join(`
|
|
149
149
|
`)}],structuredContent:{ok:!1,approval:Bo}};let Le={};ee!==void 0&&(Le.title=ee),typeof i=="string"?Le.bodyMarkdown=i:r==="create"&&(Le.bodyMarkdown=""),ve!==void 0&&(Le.category=ve),Te!==void 0&&(Le.noteClass=Te),Bt!==void 0&&(Le.nodeType=Bt),vt!==void 0&&(Le.slug=vt),u!==void 0&&(Le.tags=pn),Ke!==void 0&&(Le.canonicalPath=Ke),Pt!==void 0&&(Le.primaryNodeRef=Pt),Dt!==void 0&&(Le.canonLevel=Dt),typeof h=="boolean"&&(Le.isStructured=h),m!==void 0&&(Le.rootKind=m),g!==void 0&&(Le.linkedEpisodeIds=Go),b!==void 0&&(Le.linkedCharacterIds=Sl),$!==void 0&&(Le.graphEdges=$),S!==void 0&&(Le.timeline=S),typeof z=="number"&&(Le.baseVersion=z),Ho!==void 0&&(Le.sourceProposalSetId=Ho),Xn!==void 0&&(Le.snapshotSource=Xn);let Cw=e.localWikiStore?await e.localWikiStore.writePage({mode:r,pageId:qe,title:ee,bodyMarkdown:typeof i=="string"?i:r==="create"?"":void 0,category:ve,noteClass:Te,nodeType:Bt,slug:vt,tags:pn,canonicalPath:Ke,primaryNodeRef:Pt,canonLevel:Dt,isStructured:h,rootKind:m??void 0,linkedEpisodeIds:Go,linkedCharacterIds:Sl,graphEdges:$,timeline:S,baseVersion:z,sourceProposalSetId:Ho,snapshotSource:Xn??void 0}):r==="create"?await e.apiBridge.postJson(He(e,"/wiki"),Le):await e.apiBridge.putJson(He(e,`/wiki/${encodeURIComponent(qe??"")}`),Le);return{content:[{type:"text",text:PW({mode:r,page:Cw,approvalSource:Bo.source,rememberProject:Bo.rememberProject})}],structuredContent:{page:Cw,mode:r,approval:Bo}}}),t.registerTool("seojeom_search_wiki_pages",{title:"Search Wiki Pages",description:"Search wiki pages by title, path, tags, or section text.",inputSchema:{query:x.string().min(1),limit:x.number().int().min(1).max(100).optional()}},async({query:r,limit:o})=>{let n=e.localWikiStore?await e.localWikiStore.searchPages(r,o??20):await e.apiBridge.getJson(`${He(e,"/wiki/search")}?q=${encodeURIComponent(r)}&limit=${String(o??20)}`),i=[`[wiki search] "${n.query}" \xB7 ${n.results.length}\uAC1C`];for(let a of n.results){i.push(`- ${a.title} (${a.documentId})`),i.push(` field=${a.matchedField} \xB7 score=${a.score} \xB7 path=${a.canonicalPath??"-"}`);let s=bw(a.matchedSnippet,180);s&&i.push(` ${s}`)}return{content:[{type:"text",text:i.join(`
|
|
150
|
-
`)}],structuredContent:n}})}function Iw(t){let e=t.focusNodeId?.trim()||null;return{ok:!0,summary:"Install the MCP package into Claude, confirm which project the router bound to, then inspect the local wiki or graph surface before making changes.",install:{packageName:"seojeom-mcp",summary:"Install the MCP package in shared-registry router mode, then verify the active project binding before reading or mutating local wiki and graph data.",claudeMcpAddCommand:"claude mcp add -s local seojeom -e SEOJEOM_SHARED_REGISTRY_DIR=<shared-registry-dir> --
|
|
150
|
+
`)}],structuredContent:n}})}function Iw(t){let e=t.focusNodeId?.trim()||null;return{ok:!0,summary:"Install the MCP package into Claude, confirm which project the router bound to, then inspect the local wiki or graph surface before making changes.",install:{packageName:"seojeom-mcp",summary:"Install the MCP package in shared-registry router mode, then verify the active project binding before reading or mutating local wiki and graph data.",claudeMcpAddCommand:"claude mcp add -s local seojeom -e SEOJEOM_SHARED_REGISTRY_DIR=<shared-registry-dir> -- npm exec --yes --package=seojeom-mcp seojeom-mcp -- --router --host-kind auto --approval-mode prompt",directRunCommand:"seojeom-mcp --router --host-kind auto --registry-dir <shared-registry-dir> --approval-mode prompt",recommendedFlags:["-e SEOJEOM_SHARED_REGISTRY_DIR=<shared-registry-dir>","--router","--host-kind auto","--approval-mode prompt"],recommendedFlagsHint:"Keep the shared registry env, router mode, and approvalMode=prompt so the MCP process follows the currently open desktop or Godot project."},firstCalls:[{order:1,toolName:"seojeom_project_info",argumentsHint:{},why:"Confirm the bound project root, active authorities, and selection source before doing any authoring work."},{order:2,toolName:"seojeom_list_wiki_pages",argumentsHint:{},why:"Inspect the local wiki inventory so the session starts from real project pages instead of memory."},{order:3,toolName:"seojeom_list_nodes",argumentsHint:e?{labelContains:e,limit:10}:{limit:20},why:e?"If a focus node is already known, use graph listing to confirm the current graph has the expected local node before mutating anything.":"After confirming the project binding, inspect the current graph node inventory before choosing a concrete authoring target."}],starterPrompt:e?`Install the Seojeom MCP package, call seojeom_project_info first, then inspect local wiki and graph state with focus hint ${e} before making changes.`:"Install the Seojeom MCP package, call seojeom_project_info first, then inspect local wiki and graph state before making changes."}}function Rw(t){let e=["[claude mcp onboarding]",`summary: ${t.summary}`,`install summary: ${t.install.summary}`,`recommended flags hint: ${t.install.recommendedFlagsHint}`,`claude mcp add: ${t.install.claudeMcpAddCommand}`,`direct run: ${t.install.directRunCommand}`,`starter prompt: ${t.starterPrompt}`];for(let r of t.firstCalls)e.push(`- [${r.order}] ${r.toolName}`),e.push(` ${r.why}`);return e.join(`
|
|
151
151
|
`)}function oA(t){t.registerTool("seojeom_get_claude_mcp_onboarding",{title:"Get Claude MCP Onboarding",description:"Return the install command, recommended flags, and first core tool calls for a Claude operator using the local Seojeom MCP package.",inputSchema:{projectRootHint:x.string().min(1).optional(),focusNodeId:x.string().min(1).optional()}},async({projectRootHint:e,focusNodeId:r})=>{let o=Iw({projectRootHint:e,focusNodeId:r});return{content:[{type:"text",text:Rw(o)}],structuredContent:o}})}var IW=(t,e)=>{console.error(`[roots-protocol:${t}] ${e}`)};async function RW(t,e,r){let o=e.roots[0];if(!o){r("warn","client returned empty roots list; keeping fallback root");return}try{let n=await t.swap({uri:o.uri,name:o.name});if(r("info",`adopted client root \u2192 epoch=${n.snapshot.epoch} fsPath=${n.snapshot.fsPath} name=${n.snapshot.name}`),n.listenerErrors.length>0)for(let i of n.listenerErrors)r("warn",`listener "${i.name}" threw during swap: ${i.error}`)}catch(n){r("error",`failed to adopt client root "${o.uri}": ${n instanceof Error?n.message:String(n)}`)}}async function iA(t,e,r){if(!t.server.getClientCapabilities()?.roots){r("info","client did not declare roots capability; sticking with launch-arg root");return}try{let n=await t.server.listRoots();await RW(e,n,r)}catch(n){r("warn",`roots/list call failed: ${n instanceof Error?n.message:String(n)}`)}}function aA(t,e,r={}){let o=r.log??IW,n=r.pullInitial!==!1;if(t.server.setNotificationHandler(Ay,async()=>{o("info","received notifications/roots/list_changed; pulling new roots/list"),await iA(t,e,o)}),n){let i=t.server.oninitialized;t.server.oninitialized=()=>{try{i?.()}catch(a){o("warn",`pre-existing oninitialized handler threw: ${a instanceof Error?a.message:String(a)}`)}setImmediate(()=>{iA(t,e,o)})}}}function sA(t){let e=t?.trim().toLowerCase()??null;return e==="public"||e==="full"?e:null}function yh(t=process.env){return sA(t.SEOJEOM_MCP_SURFACE_PROFILE)??sA("public")??"full"}var jW=async()=>{},TW=async()=>{};async function zW(t,e){yh()}async function OW(t,e){yh()==="full"&&await TW(t,e)}async function cA(t,e,r){let o=new Ta({name:t.serverName,version:t.serverVersion}),n=dh(t,e,r);return await Ew(o,n),o}async function Ew(t,e){let r=yh();rA(t,e),nA(t,e),r==="public"&&oA(t),eA(t,e),tA(t,e),Y6(t,e),B6(t,e),await OW(t,e),await zW(t,e),aA(t,e.rootsService)}import Ma from"node:process";import{mkdir as AW,readFile as uA,readdir as CW,writeFile as NW}from"node:fs/promises";import{homedir as lA}from"node:os";import{join as _l}from"node:path";var DW=15e3;function Tw(t){return t.trim().replace(/\\/g,"/")}function pA(t){return t.replace(/\/+$/,"")}function MW(t,e){let r=t.trim();return r&&(e==="wsl"?dA(r)??Tw(r):LW(r)??r)}function zw(t=process.env){return t.WSL_DISTRO_NAME||t.WSL_INTEROP?"wsl":process.platform==="win32"?"windows":"wsl"}function dA(t){let e=Tw(t);if(e.startsWith("//"))return null;let r=e.match(/^([A-Za-z]):(?:\/(.*))?$/);if(!r)return null;let o=r[1].toLowerCase(),n=r[2]??"";return pA(`/mnt/${o}/${n}`)}function LW(t){let r=Tw(t).match(/^\/mnt\/([A-Za-z])(?:\/(.*))?$/);if(!r)return null;let o=r[1].toUpperCase(),n=r[2]??"";return pA(`${o}:/${n}`)}function fA(t){let e=t.env??process.env,r=t.hostKind??zw(e),o=t.explicitDir?.trim()??e.SEOJEOM_SHARED_REGISTRY_DIR?.trim()??"";if(o)return MW(o,r);if(r==="windows"){let a=e.USERPROFILE?.trim()||lA();return _l(a,".seojeom","registry")}let n=e.USERPROFILE?.trim()??"";if(n){let a=dA(n);if(a)return`${a}/.seojeom/registry`}let i=e.HOME?.trim()||lA();return _l(i,".seojeom","registry")}function jw(t){return _l(t,"projects")}function mA(t){return _l(t,"active.json")}async function hA(t){await AW(jw(t),{recursive:!0})}function gA(t){try{return JSON.parse(t)}catch{return null}}async function qW(t){await hA(t);let e=[],r=await CW(jw(t)).catch(()=>[]);for(let o of r){if(!o.endsWith(".json"))continue;let n=await uA(_l(jw(t),o),"utf8").catch(()=>null);if(!n)continue;let i=gA(n);!i||!i.projectHash||!i.projectId||e.push(i)}return e}async function Da(t){let e=await uA(mA(t),"utf8").catch(()=>null);return e?gA(e):null}async function vA(t,e){await hA(t),await NW(mA(t),`${JSON.stringify(e,null,2)}
|
|
152
152
|
`,"utf8")}function bl(t){let e=t.trim();if(!e)return 0;let r=/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/.test(e)?`${e.replace(" ","T")}Z`:e,o=Date.parse(r);return Number.isFinite(o)?o:0}function UW(t,e={}){let r=e.nowMs??Date.now(),o=e.staleTtlMs??DW,n=bl(t.heartbeatAt);return n<=0?!1:r-n<=o}function ZW(t,e){let r=e==="windows"?t.paths.windows:t.paths.wsl,o=e==="windows"?t.hostSupport.windows&&!!r:t.hostSupport.wsl&&!!r,n=o?null:e==="windows"?t.hostSupport.windowsReason??`project ${t.projectId} is not supported on Windows router`:t.hostSupport.wslReason??`project ${t.projectId} is not supported on WSL router`;return{...t,isLive:!0,supportedOnHost:o,resolvedProjectRoot:r,unavailableReason:n}}function FW(t,e){let r=bl(t.lastActiveAt),o=bl(e.lastActiveAt);if(r!==o)return o-r;let n=bl(t.heartbeatAt),i=bl(e.heartbeatAt);return n!==i?i-n:t.projectId.localeCompare(e.projectId)}async function Vo(t){return(await qW(t.registryDir)).filter(r=>UW(r,{nowMs:t.nowMs,staleTtlMs:t.staleTtlMs})).sort(FW).map(r=>ZW(r,t.hostKind))}function VW(t){let e=t.supportedOnHost?t.resolvedProjectRoot:`unsupported: ${t.unavailableReason}`;return` - ${t.projectId} (hash=${t.projectHash}, root=${t.projectRootName}, host=${e})`}function wl(t,e,r){if(t.length===0)throw new Error("no live Seojeom project found in shared registry. Open a project in the Godot desktop app first.");let o=r?.trim()||e?.projectHash||"";if(o){let i=t.find(a=>a.projectHash===o);if(!i)throw new Error(`active project hash=${o} is not live anymore. Call seojeom_list_projects to inspect current options.`);if(!i.supportedOnHost)throw new Error(`project ${i.projectId} (hash=${i.projectHash}) is unavailable on this host: ${i.unavailableReason}`);return i}if(t.length===1){let i=t[0];if(!i.supportedOnHost)throw new Error(`the only live project ${i.projectId} is unavailable on this host: ${i.unavailableReason}`);return i}let n=t.map(VW).join(`
|
|
153
153
|
`);throw new Error(`multiple live Seojeom projects detected; choose one with seojeom_set_active_project:
|
|
154
154
|
${n}`)}function xh(t){return{projectId:t.projectId,projectHash:t.projectHash,projectRootName:t.projectRootName,resolvedProjectRoot:t.resolvedProjectRoot,supportedOnHost:t.supportedOnHost,unavailableReason:t.unavailableReason,heartbeatAt:t.heartbeatAt,lastActiveAt:t.lastActiveAt,sidecar:t.sidecar}}async function yA(t){let e=await Vo(t),r=await Da(t.registryDir),o={registryDir:t.registryDir,hostKind:t.hostKind,activePointer:r,preferredProjectHash:t.preferredProjectHash??null,projects:e.map(xh)};return{content:[{type:"text",text:JSON.stringify(o,null,2)}],structuredContent:o}}async function xA(t,e){let r=e.projectHash.trim();if(!r)throw new Error("projectHash is required");let n=(await Vo(t)).find(i=>i.projectHash===r);if(!n)throw new Error(`no live shared-registry project with hash=${r}; call seojeom_list_projects to inspect current options`);if(!n.supportedOnHost)throw new Error(`project ${n.projectId} (hash=${n.projectHash}) is unavailable on ${t.hostKind}: ${n.unavailableReason}`);return await vA(t.registryDir,{projectHash:n.projectHash,setAt:new Date().toISOString(),setBy:`router:${t.hostKind}`}),await t.onProjectSelected?.(n),{content:[{type:"text",text:`active project set to ${n.projectId} (hash=${n.projectHash}, root=${n.resolvedProjectRoot})`}],structuredContent:xh(n)}}async function bA(t){let e=await Vo(t),r=await Da(t.registryDir),o=null,n=null;try{o=xh(wl(e,r,null))}catch(a){n=a instanceof Error?a.message:String(a)}let i={registryDir:t.registryDir,hostKind:t.hostKind,activePointer:r,clearedPreferredProjectHash:t.preferredProjectHash??null,selectedProject:o,selectionError:n};return{content:[{type:"text",text:JSON.stringify(i,null,2)}],structuredContent:i}}async function _A(t){let e=await Vo(t),r=await Da(t.registryDir),o=null,n=null;try{o=xh(wl(e,r,t.preferredProjectHash??null))}catch(a){n=a instanceof Error?a.message:String(a)}let i={mode:"shared-registry-router-local",registryDir:t.registryDir,hostKind:t.hostKind,liveProjectCount:e.length,activePointer:r,preferredProjectHash:t.preferredProjectHash??null,selectedProject:o,selectionError:n};return{content:[{type:"text",text:JSON.stringify(i,null,2)}],structuredContent:i}}function Ow(t,e){let r=`${e}=`,o=t.find(a=>a.startsWith(r));if(o)return o.slice(r.length).trim()||null;let n=t.indexOf(e);if(n===-1)return null;let i=t[n+1];if(!i||i.startsWith("--"))throw new Error(`missing value for ${e}`);return i.trim()||null}function GW(t,e){let r=[];for(let o=0;o<t.length;o+=1){let n=t[o],i=e.find(a=>n===a||n.startsWith(`${a}=`));if(!i){r.push(n);continue}n===i&&(o+=1)}return r}function HW(t,e){let r=Ow(t,"--host-kind")??e.SEOJEOM_MCP_ROUTER_HOST_KIND??"auto",o=r.trim().toLowerCase();if(o!=="auto"&&o!=="windows"&&o!=="wsl")throw new Error(`invalid --host-kind value: ${r} (expected auto, windows, or wsl)`);let n=o;return n==="auto"?zw(e):n}function BW(t,e){let r=Ow(t,"--approval-mode")??e.SEOJEOM_MCP_APPROVAL_MODE??"prompt",o=r.trim().toLowerCase();if(o==="always"||o==="never"||o==="prompt")return o;throw new Error(`invalid --approval-mode value: ${r} (expected prompt, always, or never)`)}async function wA(t){let e=await Vo(t),r=await Da(t.registryDir);try{return wl(e,r,t.preferredProjectHash??null)}catch{return null}}function JW(t){let e=GW(t.argv,["--router","--registry-dir","--host-kind","--project-root","--project-id","--wiki-authority","--graph-authority"]);return{...Wd(["--project-root",t.selectedProject?.resolvedProjectRoot??t.registryDir,"--project-id",t.selectedProject?.projectId??"router-unselected","--wiki-authority","local-filesystem","--graph-authority","local-snapshot",...e],{...t.env,SEOJEOM_MCP_WIKI_AUTHORITY:"local-filesystem",SEOJEOM_MCP_GRAPH_AUTHORITY:"local-snapshot"}),transport:"stdio",serverName:"seojeom-router",serverVersion:t.serverVersion}}async function SA(t){let e=t.argv??Ma.argv.slice(2),r=t.env??Ma.env,o=HW(e,r),n=BW(e,r),i=fA({explicitDir:Ow(e,"--registry-dir"),env:r,hostKind:o}),a=null,s=await wA({registryDir:i,hostKind:o,preferredProjectHash:a}),c=new Ei(s?{projectId:s.projectId,projectRoot:s.resolvedProjectRoot,projectHash:s.projectHash,projectRootName:s.projectRootName,source:"shared-registry"}:null),l=JW({argv:e,env:r,registryDir:i,selectedProject:s,serverVersion:t.serverVersion}),u=new ji({projectId:l.projectId,projectIdProvider:c,mode:n}),p=dh(l,0,u,{projectRuntime:c}),d=new Ta({name:"seojeom-router",version:t.serverVersion}),f=async k=>{let J=c.getSnapshot();if(!k)return c.clearSelection({source:"shared-registry"}),null;if(!k.resolvedProjectRoot)throw new Error(`selected project ${k.projectId} does not have a resolved root for ${o}`);return c.setSelection({projectId:k.projectId,projectRoot:k.resolvedProjectRoot,projectHash:k.projectHash,projectRootName:k.projectRootName,source:"shared-registry"}),(J.projectId!==k.projectId||J.projectRoot!==k.resolvedProjectRoot||J.projectHash!==k.projectHash)&&await p.rootsService.swap({fsPath:k.resolvedProjectRoot,name:k.projectRootName??void 0}),k},h=async()=>{let k=await wA({registryDir:i,hostKind:o,preferredProjectHash:a});return f(k)},m=d,g=d.registerTool.bind(d),b=g;m.registerTool=((k,J,ee)=>b(k,J,async(qe,ve)=>(await h(),ee(qe,ve)))),await Ew(d,p),m.registerTool=g,d.registerTool("seojeom_list_projects",{title:"List Shared Registry Projects",description:"List live projects discovered from the shared Godot registry for the current host."},async()=>(await h(),yA({registryDir:i,hostKind:o,preferredProjectHash:a}))),d.registerTool("seojeom_set_active_project",{title:"Set Active Shared Registry Project",description:"Select the active shared-registry project by project hash for this router session and write the active pointer.",inputSchema:{projectHash:x.string().min(1)}},async({projectHash:k})=>{let J=k.trim();return xA({registryDir:i,hostKind:o,preferredProjectHash:J,onProjectSelected:async ee=>{a=ee.projectHash,await f(ee)}},{projectHash:J})}),d.registerTool("seojeom_clear_project_override",{title:"Clear Session Project Override",description:"Clear the router session's preferred project hash and fall back to the shared active pointer or auto-selection rules."},async()=>{let k=a;return a=null,await h(),bA({registryDir:i,hostKind:o,preferredProjectHash:k})}),d.registerTool("seojeom_router_status",{title:"Shared Registry Router Status",description:"Show router host kind, shared registry path, active pointer, and current selection diagnostics."},async()=>(await h(),_A({registryDir:i,hostKind:o,preferredProjectHash:a})));let $=new Ii,S=!1,z=async()=>{if(!S){S=!0;try{await d.close()}finally{await $.close().catch(()=>{})}}};$.onerror=k=>{Ma.stderr.write(`[seojeom-router] stdio transport error: ${k.message}
|
|
155
|
-
`)},$.onclose=()=>{z().finally(()=>{Ma.exit(0)})};for(let k of["SIGINT","SIGTERM"])Ma.on(k,()=>{z().finally(()=>{Ma.exit(0)})});await d.connect($)}function Aw(t,e){let r=`${e}=`,o=t.find(a=>a.startsWith(r));if(o)return o.slice(r.length).trim()||null;let n=t.indexOf(e);if(n===-1)return null;let i=t[n+1];if(!i||i.startsWith("--"))throw new Error(`missing value for ${e}`);return i.trim()||null}function WW(t=gt.argv.slice(2),e=gt.env){let r=Aw(t,"--approval-mode")??e.SEOJEOM_MCP_APPROVAL_MODE??"prompt",o=r.trim().toLowerCase();if(o==="always"||o==="never"||o==="prompt")return o;throw new Error(`invalid --approval-mode value: ${r} (expected prompt, always, or never)`)}function XW(t){return{...t,SEOJEOM_MCP_WIKI_AUTHORITY:t.SEOJEOM_MCP_WIKI_AUTHORITY??t.SEOJEOM_DESKTOP_MCP_WIKI_AUTHORITY??"local-filesystem",SEOJEOM_MCP_GRAPH_AUTHORITY:t.SEOJEOM_MCP_GRAPH_AUTHORITY??t.SEOJEOM_DESKTOP_MCP_GRAPH_AUTHORITY??"local-snapshot"}}function QW(t=gt.argv.slice(2),e=gt.env){return{...Wd(t,XW(e)),transport:"stdio",serverName:"seojeom-mcp"}}function YW(){gt.stdout.write(["seojeom-mcp","","stdio MCP server for Claude/Codex local project access.","","recommended router/shared-registry flags:"," --router shared-registry local-execution mode"," --registry-dir <path> override shared registry dir"," --host-kind <auto|windows|wsl> router host resolution"," --approval-mode <prompt|always|never> default: prompt","","recommended router example:"," seojeom-mcp --router --host-kind auto --registry-dir C:/Users/<you>/.seojeom/registry --approval-mode prompt","","recommended Claude install example:"," claude mcp add -s local seojeom -e SEOJEOM_SHARED_REGISTRY_DIR=C:/Users/<you>/.seojeom/registry --
|
|
155
|
+
`)},$.onclose=()=>{z().finally(()=>{Ma.exit(0)})};for(let k of["SIGINT","SIGTERM"])Ma.on(k,()=>{z().finally(()=>{Ma.exit(0)})});await d.connect($)}function Aw(t,e){let r=`${e}=`,o=t.find(a=>a.startsWith(r));if(o)return o.slice(r.length).trim()||null;let n=t.indexOf(e);if(n===-1)return null;let i=t[n+1];if(!i||i.startsWith("--"))throw new Error(`missing value for ${e}`);return i.trim()||null}function WW(t=gt.argv.slice(2),e=gt.env){let r=Aw(t,"--approval-mode")??e.SEOJEOM_MCP_APPROVAL_MODE??"prompt",o=r.trim().toLowerCase();if(o==="always"||o==="never"||o==="prompt")return o;throw new Error(`invalid --approval-mode value: ${r} (expected prompt, always, or never)`)}function XW(t){return{...t,SEOJEOM_MCP_WIKI_AUTHORITY:t.SEOJEOM_MCP_WIKI_AUTHORITY??t.SEOJEOM_DESKTOP_MCP_WIKI_AUTHORITY??"local-filesystem",SEOJEOM_MCP_GRAPH_AUTHORITY:t.SEOJEOM_MCP_GRAPH_AUTHORITY??t.SEOJEOM_DESKTOP_MCP_GRAPH_AUTHORITY??"local-snapshot"}}function QW(t=gt.argv.slice(2),e=gt.env){return{...Wd(t,XW(e)),transport:"stdio",serverName:"seojeom-mcp"}}function YW(){gt.stdout.write(["seojeom-mcp","","stdio MCP server for Claude/Codex local project access.","","recommended router/shared-registry flags:"," --router shared-registry local-execution mode"," --registry-dir <path> override shared registry dir"," --host-kind <auto|windows|wsl> router host resolution"," --approval-mode <prompt|always|never> default: prompt","","recommended router example:"," seojeom-mcp --router --host-kind auto --registry-dir C:/Users/<you>/.seojeom/registry --approval-mode prompt","","recommended Claude install example:"," claude mcp add -s local seojeom -e SEOJEOM_SHARED_REGISTRY_DIR=C:/Users/<you>/.seojeom/registry -- npm exec --yes --package=seojeom-mcp seojeom-mcp -- --router --host-kind auto --approval-mode prompt","","recommended router tools:"," seojeom_list_projects"," seojeom_set_active_project"," seojeom_clear_project_override"," seojeom_router_status","","direct standalone fallback flags:"," --project-root <path>"," --project-id <id>"," --api-base-url <url> default: http://127.0.0.1:3000","","direct standalone defaults:"," wikiAuthority=local-filesystem"," graphAuthority=local-snapshot","","optional direct standalone flags:"," --graph-authority <api-bridge|local-snapshot>"," --graph-slice-path <path>"," --wiki-authority <api-bridge|local-filesystem>","","shared flags:"," --approval-mode <prompt|always|never> default: prompt","","direct standalone example:"," seojeom-mcp --project-root . --project-id demo --graph-authority local-snapshot --approval-mode prompt","","pre-install onboarding:"," seojeom-mcp --print-claude-onboarding --project-root . --focus-node-id character:serin"," seojeom-mcp --print-claude-onboarding-json --project-root .","","recommended first MCP tool call after install:"," seojeom_get_claude_mcp_onboarding"].join(`
|
|
156
156
|
`))}async function eX(){let t=gt.argv.slice(2);if(t.includes("--help")||t.includes("-h")){YW();return}if(t.includes("--print-claude-onboarding")||t.includes("--print-claude-onboarding-json")){let c=Iw({projectRootHint:Aw(t,"--project-root"),focusNodeId:Aw(t,"--focus-node-id")}),l=t.includes("--print-claude-onboarding-json");gt.stdout.write(l?`${JSON.stringify(c,null,2)}
|
|
157
157
|
`:`${Rw(c)}
|
|
158
158
|
`);return}if(t.includes("--router")){await SA({argv:t,env:gt.env,serverVersion:"0.2.0-router-local"});return}let e=QW(t,gt.env),r=WW(t);if(!KW(e.projectRoot))throw new Error(`project root does not exist: ${e.projectRoot}`);gt.chdir(e.projectRoot);let o=new ji({projectId:e.projectId,mode:r}),n=await cA(e,0,o),i=new Ii,a=!1,s=async()=>{if(!a){a=!0;try{await n.close()}finally{await i.close().catch(()=>{})}}};i.onerror=c=>{gt.stderr.write(`[seojeom-mcp] stdio transport error: ${c.message}
|