@ours.network/mcp 1.2.0-nightly.3 → 1.2.0-nightly.4
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 +19 -0
- package/dist/cli.js +3 -3
- package/dist/connector.js +1 -1
- package/dist/host-client.js +3 -3
- package/dist/host-profile.js +1 -1
- package/dist/native-session.js +2 -2
- package/dist/network-integration.js +2 -2
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -184,3 +184,22 @@ application visibility, file transfer and notification operations. Standard
|
|
|
184
184
|
uses the daemon state directory (`OURS_STATE_DIR`, default `/var/lib/ours`) and its
|
|
185
185
|
private `.mcp` profile; it is an internal launcher interface, not an additional
|
|
186
186
|
service or a replacement for normal host startup.
|
|
187
|
+
|
|
188
|
+
### Remote clients over HTTPS
|
|
189
|
+
|
|
190
|
+
A client may select an `https://` origin backed by a TLS reverse proxy. Keep the
|
|
191
|
+
daemon listener private and configure the proxy separately with a certificate
|
|
192
|
+
trusted by the client and matching the hostname. Node uses its normal trust
|
|
193
|
+
store; a private CA may be supplied through `NODE_EXTRA_CA_CERTS` before starting
|
|
194
|
+
the client. Certificate verification must remain enabled.
|
|
195
|
+
|
|
196
|
+
The existing issued client credential works over either transport; changing the
|
|
197
|
+
URL scheme does not require a new credential. Keep the server's master on the
|
|
198
|
+
server. Forward `x-ours-api-token` and the `x-ours-*` session headers unchanged,
|
|
199
|
+
and support streamed request/response bodies and long polling. Client requests
|
|
200
|
+
refuse redirects, including HTTPS-to-HTTP redirects: configure the final HTTPS
|
|
201
|
+
origin directly. UUID/capability checks still precede credential-bearing calls.
|
|
202
|
+
|
|
203
|
+
This adds client HTTPS support, not an HTTPS daemon listener, certificate
|
|
204
|
+
provisioning or automatic reverse-proxy configuration. Existing local HTTP and
|
|
205
|
+
SSH-tunnel profiles continue to work.
|
package/dist/cli.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import{spawn as Gt}from"node:child_process";import{readFileSync as Vt,realpathSync as V}from"node:fs";import{fileURLToPath as Wt}from"node:url";import{attachOursClient as B,resolveDaemonConfig as Yt}from"@ours.network/sdk";import{randomUUID as z}from"node:crypto";import{chmod as X,mkdir as Q,readFile as Z,rename as tt,unlink as et,writeFile as nt}from"node:fs/promises";import{homedir as rt}from"node:os";import{dirname as it,resolve as u}from"node:path";var R=1,ot="OURS_MCP_CONFIG",T=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/,st=()=>({version:1,daemons:{},instances:{}});function v(t=process.env){let e=(t[ot]??"").trim();return u(e||u(rt(),".ours-mcp","config.json"))}function x(t,e,n,r){if(!t||typeof t!="object"||Array.isArray(t))throw new Error(`Invalid ours-mcp application identity config at ${e}: "${n}s" must be an object.`);let i={};for(let[o,s]of Object.entries(t)){if(!s||typeof s!="object"||Array.isArray(s))throw new Error(`Invalid ours-mcp application identity config at ${e}: ${n} ${JSON.stringify(o)} must be an object.`);let a=s;if(!Array.isArray(a.identities)||a.identities.some(l=>typeof l!="string"||l.length===0))throw new Error(`Invalid ours-mcp application identity config at ${e}: ${n} ${JSON.stringify(o)} has an invalid identity list.`);i[r(o)]={identities:[...new Set(a.identities)].sort()}}return i}function at(t,e){let n;try{n=JSON.parse(t)}catch(s){throw new Error(`Invalid ours-mcp application identity config at ${e}: ${String(s)}`)}if(!n||typeof n!="object"||Array.isArray(n))throw new Error(`Invalid ours-mcp application identity config at ${e}: expected an object.`);let r=n;if(r.version!==R)throw new Error(`Unsupported ours-mcp application identity config version at ${e}: expected ${R}, found ${String(r.version)}.`);let i=x(r.daemons,e,"daemon",u),o=r.instances===void 0?{}:x(r.instances,e,"instance",s=>{if(!T.test(s))throw new Error(`Invalid ours-mcp application identity config at ${e}: instance ${JSON.stringify(s)} must be a lowercase UUID.`);return s});return{version:1,daemons:i,instances:o}}async function y(t){try{return at(await Z(t,"utf8"),t)}catch(e){if(e.code==="ENOENT")return st();throw e}}async function _(t,e){let n=it(t);await Q(n,{recursive:!0,mode:448});let r=`${t}.${process.pid}.${z()}.tmp`;try{await nt(r,`${JSON.stringify(e,null,2)}
|
|
3
|
-
`,{mode:384,flag:"wx"}),await tt(r,t),await X(t,384)}catch(i){try{await et(r)}catch{}throw i}}var f=class{stateDir;instanceId;path;constructor(e,n={}){if(typeof e=="string")this.stateDir=u(e),this.instanceId=null;else{if(!e||!T.test(e.instanceId))throw new Error("Application identity instanceId must be a lowercase UUID.");this.stateDir=null,this.instanceId=e.instanceId}this.path=u(n.path??v(n.env))}rows(e){return this.instanceId===null?e.daemons:e.instances}key(){return this.instanceId??this.stateDir}async list(){let e=await y(this.path);return[...this.rows(e)[this.key()]?.identities??[]]}async has(e){return(await this.list()).includes(e)}async add(e){if(!e)throw new Error("Cannot add an empty identity name to ours-mcp.");let n=await y(this.path),r=this.rows(n),i=this.key(),o=r[i]?.identities??[];o.includes(e)||(r[i]={identities:[...o,e].sort()},await _(this.path,n))}async remove(e){let n=await y(this.path),r=this.rows(n),i=this.key(),o=r[i];if(!o?.identities.includes(e))return;let s=o.identities.filter(a=>a!==e);s.length===0?delete r[i]:r[i]={identities:s},await _(this.path,n)}};async function $(t,e){let n=new Set(await t.list());return e.filter(r=>n.has(r.name))}import{existsSync as ct,lstatSync as U,readFileSync as dt}from"node:fs";import{homedir as A}from"node:os";import{resolve as m}from"node:path";var I=["endpoint","expectedInstanceId","credentialPath"],lt=["port","stateDir","apiToken","apiVisibility"],pt=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/,ut=["OURS_API_TOKEN","OURS_PORT","OURS_STATE_DIR","OURS_DAEMON_ID"];function d(t){return new Error(`Invalid external host profile: ${t}`)}function E(t){if(!t||typeof t!="object"||Array.isArray(t))throw d("expected a complete host profile object.");let e=t;if(I.filter(l=>Object.hasOwn(e,l)).length!==I.length)throw d("expected a complete host profile tuple: endpoint, expectedInstanceId, credentialPath.");let r=lt.filter(l=>Object.hasOwn(e,l));if(r.length)throw d(`legacy selection keys cannot be mixed with a host profile (${r.join(", ")}).`);let i=e.endpoint,o=e.expectedInstanceId,s=e.credentialPath;if(typeof i!="string"||i.trim()!==i||i==="")throw d("endpoint must be a non-empty HTTP origin.");if(typeof o!="string"||!pt.test(o))throw d("expectedInstanceId must be a lowercase UUID.");if(typeof s!="string"||s===""||!s.startsWith("/")||m(s)!==s)throw d("credentialPath must be a normalized absolute path.");let a;try{a=new URL(i)}catch{throw d("endpoint must be an HTTP origin.")}if(a.protocol!=="http:"||a.username||a.password||a.pathname!=="/"||a.search||a.hash)throw d("endpoint must be an HTTP origin without credentials, path, query, or fragment.");return{endpoint:a.origin,expectedInstanceId:o,credentialPath:s}}function ft(t){let e;try{e=dt(t,"utf8")}catch{throw new Error(`Cannot read host profile ${JSON.stringify(t)}.`)}let n;try{n=JSON.parse(e)}catch{throw d(`config ${JSON.stringify(t)} is not valid JSON.`)}if(!n||typeof n!="object"||Array.isArray(n))throw d(`config ${JSON.stringify(t)} must be an object.`);return n}function mt(t){let e;try{e=U(t)}catch{throw new Error(`Cannot read host profile ${JSON.stringify(t)}.`)}if(!e.isFile())throw d(`config ${JSON.stringify(t)} must be a regular file.`);let n=process.getuid?.();if(n===void 0||e.uid!==n)throw d(`config ${JSON.stringify(t)} must be owned by the current user.`);if(e.mode&63)throw d(`config ${JSON.stringify(t)} must have private permissions.`)}function wt(t){let e=ft(t);return I.filter(r=>Object.hasOwn(e,r)).length===0?null:(mt(t),E(e))}function
|
|
4
|
-
`,{mode:384,flag:"wx"}),await _t(r,t),await j(t,384)}catch(i){try{await Tt(r)}catch{}throw i}}async function jt(t,e){let n=
|
|
3
|
+
`,{mode:384,flag:"wx"}),await tt(r,t),await X(t,384)}catch(i){try{await et(r)}catch{}throw i}}var f=class{stateDir;instanceId;path;constructor(e,n={}){if(typeof e=="string")this.stateDir=u(e),this.instanceId=null;else{if(!e||!T.test(e.instanceId))throw new Error("Application identity instanceId must be a lowercase UUID.");this.stateDir=null,this.instanceId=e.instanceId}this.path=u(n.path??v(n.env))}rows(e){return this.instanceId===null?e.daemons:e.instances}key(){return this.instanceId??this.stateDir}async list(){let e=await y(this.path);return[...this.rows(e)[this.key()]?.identities??[]]}async has(e){return(await this.list()).includes(e)}async add(e){if(!e)throw new Error("Cannot add an empty identity name to ours-mcp.");let n=await y(this.path),r=this.rows(n),i=this.key(),o=r[i]?.identities??[];o.includes(e)||(r[i]={identities:[...o,e].sort()},await _(this.path,n))}async remove(e){let n=await y(this.path),r=this.rows(n),i=this.key(),o=r[i];if(!o?.identities.includes(e))return;let s=o.identities.filter(a=>a!==e);s.length===0?delete r[i]:r[i]={identities:s},await _(this.path,n)}};async function $(t,e){let n=new Set(await t.list());return e.filter(r=>n.has(r.name))}import{existsSync as ct,lstatSync as U,readFileSync as dt}from"node:fs";import{homedir as A}from"node:os";import{resolve as m}from"node:path";var I=["endpoint","expectedInstanceId","credentialPath"],lt=["port","stateDir","apiToken","apiVisibility"],pt=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/,ut=["OURS_API_TOKEN","OURS_PORT","OURS_STATE_DIR","OURS_DAEMON_ID"];function d(t){return new Error(`Invalid external host profile: ${t}`)}function E(t){if(!t||typeof t!="object"||Array.isArray(t))throw d("expected a complete host profile object.");let e=t;if(I.filter(l=>Object.hasOwn(e,l)).length!==I.length)throw d("expected a complete host profile tuple: endpoint, expectedInstanceId, credentialPath.");let r=lt.filter(l=>Object.hasOwn(e,l));if(r.length)throw d(`legacy selection keys cannot be mixed with a host profile (${r.join(", ")}).`);let i=e.endpoint,o=e.expectedInstanceId,s=e.credentialPath;if(typeof i!="string"||i.trim()!==i||i==="")throw d("endpoint must be a non-empty HTTP or HTTPS origin.");if(typeof o!="string"||!pt.test(o))throw d("expectedInstanceId must be a lowercase UUID.");if(typeof s!="string"||s===""||!s.startsWith("/")||m(s)!==s)throw d("credentialPath must be a normalized absolute path.");let a;try{a=new URL(i)}catch{throw d("endpoint must be an HTTP or HTTPS origin.")}if(a.protocol!=="http:"&&a.protocol!=="https:"||a.username||a.password||a.pathname!=="/"||a.search||a.hash)throw d("endpoint must be an HTTP or HTTPS origin without credentials, path, query, or fragment.");return{endpoint:a.origin,expectedInstanceId:o,credentialPath:s}}function ft(t){let e;try{e=dt(t,"utf8")}catch{throw new Error(`Cannot read host profile ${JSON.stringify(t)}.`)}let n;try{n=JSON.parse(e)}catch{throw d(`config ${JSON.stringify(t)} is not valid JSON.`)}if(!n||typeof n!="object"||Array.isArray(n))throw d(`config ${JSON.stringify(t)} must be an object.`);return n}function mt(t){let e;try{e=U(t)}catch{throw new Error(`Cannot read host profile ${JSON.stringify(t)}.`)}if(!e.isFile())throw d(`config ${JSON.stringify(t)} must be a regular file.`);let n=process.getuid?.();if(n===void 0||e.uid!==n)throw d(`config ${JSON.stringify(t)} must be owned by the current user.`);if(e.mode&63)throw d(`config ${JSON.stringify(t)} must have private permissions.`)}function wt(t){let e=ft(t);return I.filter(r=>Object.hasOwn(e,r)).length===0?null:(mt(t),E(e))}function ht(t,e){return(t[e]??"").trim()!==""}function gt(t=process.env){let e=(t.OURS_CONFIG??"").trim(),n=m(t.HOME||A(),".ours-client","profile.json"),r=e;if(!r)try{U(n),r=n}catch(s){if(s.code!=="ENOENT")throw new Error(`Cannot read host profile ${JSON.stringify(n)}.`);if(r=m(A(),".ours","config.json"),!ct(r))return null}let i=wt(r);if(i===null){if(m(r)===n)throw d("managed client config must contain a complete host profile tuple.");return null}let o=ut.filter(s=>ht(t,s));if(o.length)throw d(`${o.join(", ")} conflicts with host-profile mode.`);return{profile:i,configPath:r}}function S(t=process.env){return gt(t)?.profile??null}import{createHash as bt,randomUUID as Ct}from"node:crypto";import{chmod as j,mkdir as Rt,readFile as xt,rename as _t,unlink as Tt,writeFile as $t}from"node:fs/promises";import{dirname as H,join as At,resolve as Ut}from"node:path";import{attachOursClient as kt}from"@ours.network/sdk";import{createHash as yt}from"node:crypto";import{openSync as vt,closeSync as It,lstatSync as N,mkdirSync as Et,chmodSync as St,constants as w}from"node:fs";import{join as k}from"node:path";import{createRequire as D}from"node:module";var Nt=5e3,p=null,L=!1;function Ot(){if(p)return p;if(L)throw new Error("No SQLite implementation available for native session guard");L=!0;try{return p=D(import.meta.url)("node:sqlite").DatabaseSync,p}catch{try{let t=D(import.meta.url)("better-sqlite3");return p=t.default??t,p}catch{throw new Error("Native session guard requires node:sqlite (Node >=22.13) or better-sqlite3")}}}function Pt(t){try{let n=vt(t,w.O_RDWR|w.O_CREAT|w.O_EXCL|w.O_NOFOLLOW,384);It(n)}catch(n){if(n.code!=="EEXIST")throw n}let e=N(t);if(!e.isFile()||e.uid!==process.getuid()||e.mode&63||e.nlink!==1)throw new Error("Native session guard file must be an owner-only regular file")}function J(t){let e=process.getuid(),n=k(`/tmp/ours-${e}`,"session-guards");Et(n,{recursive:!0,mode:448});try{St(n,448)}catch{}let r=yt("sha256").update(t).digest("hex"),i=k(n,`${r}.guard`);Pt(i);let o=N(i),s=Ot(),a=new s(i);try{let l=N(i);if(o.dev!==l.dev||o.ino!==l.ino||o.mode!==l.mode||o.uid!==l.uid)throw new Error("Native session guard file changed during acquisition");return a.exec(`PRAGMA busy_timeout=${Nt}; BEGIN EXCLUSIVE`),()=>{try{a.close()}catch{}}}catch(l){try{a.close()}catch{}throw l}}var P=1,F=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/,O=new Map,h=new Map;function Dt(t){if(typeof t!="string"||t.length===0||t.length>4096||t.trim()!==t||t.includes("\0"))throw new Error("Native session metadata is missing or invalid for this host-profile tool call.");return t}function Lt(t,e,n){if(!t||!t.startsWith("/")||Ut(t)!==t)throw new Error("Native session host record root must be a normalized absolute path.");if(!F.test(e))throw new Error("Native session daemon instance must be a lowercase UUID.");let r=bt("sha256").update(Dt(n),"utf8").digest("hex");return At(t,"sessions",e,`${r}.json`)}function Jt(t,e){let n;try{n=JSON.parse(t)}catch(o){throw new Error(`Invalid native session record at ${e}: ${String(o)}`)}if(!n||typeof n!="object"||Array.isArray(n))throw new Error(`Invalid native session record at ${e}: expected an object.`);let r=n;if(Object.keys(r).sort().join(",")!=="ownerInstanceId,state,version"||r.version!==P||typeof r.ownerInstanceId!="string"||!F.test(r.ownerInstanceId)||!["active","pending","ended"].includes(String(r.state)))throw new Error(`Invalid native session record at ${e}.`);return r}async function M(t){try{return Jt(await xt(t,"utf8"),t)}catch(e){if(e.code==="ENOENT")return null;throw e}}async function q(t,e){let n=H(t);await Rt(n,{recursive:!0,mode:448}),await j(n,448);let r=`${t}.${process.pid}.${Ct()}.tmp`;try{await $t(r,`${JSON.stringify(e,null,2)}
|
|
4
|
+
`,{mode:384,flag:"wx"}),await _t(r,t),await j(t,384)}catch(i){try{await Tt(r)}catch{}throw i}}async function jt(t,e){let n=h.get(t)??Promise.resolve(),r,i=new Promise(a=>{r=a}),o=n.catch(()=>{}).then(()=>i);h.set(t,o),await n.catch(()=>{});let s;try{return s=J(t),await e()}finally{try{s?.()}finally{r(),h.get(t)===o&&h.delete(t)}}}function Ht(t,e){return kt({endpoint:t.endpoint,expectedInstanceId:t.expectedInstanceId,credentialPath:t.credentialPath,sessionMode:"external",leaseToken:e,env:{}})}async function Ft(t,e,n){let r=O.get(t),i=r?.ownerInstanceId===n?await r.promise:await Ht(e,n);try{await i.releaseLease()}finally{r?.ownerInstanceId!==n&&await i.close()}}async function Mt(t,e,n){await Ft(t,e,n);let r=await M(t);r?.state==="pending"&&r.ownerInstanceId===n&&await q(t,{version:P,ownerInstanceId:n,state:"ended"});let i=O.get(t);i?.ownerInstanceId===n&&(O.delete(t),i.promise.then(o=>o.close()).catch(()=>{}))}async function G(t,e,n=process.env){return qt(t,e,H(v(n)))}async function qt(t,e,n){let r=E(t),i=Lt(n,r.expectedInstanceId,e);await jt(i,async()=>{let o=await M(i);o===null||o.state==="ended"||(o.state==="active"&&(o={version:P,ownerInstanceId:o.ownerInstanceId,state:"pending"},await q(i,o)),await Mt(i,r,o.ownerInstanceId))})}var b="1.2.0-nightly.4",c=t=>{process.stdout.write(`${t}
|
|
5
5
|
`)},K=t=>{process.stderr.write(`${t}
|
|
6
|
-
`)},W=t=>Number.isInteger(t)&&t>1,Y=Number(process.env.OURS_CLIENT_PID),
|
|
6
|
+
`)},W=t=>Number.isInteger(t)&&t>1,Y=Number(process.env.OURS_CLIENT_PID),g=W(Y)?Y:W(process.ppid)?process.ppid:process.pid,C=(process.env.CLAUDE_CODE_SESSION_ID??"").trim()||`ours-mcp:${g}`,Bt=(process.env.OURS_BIND_IDENTITY??"").trim()||void 0,Kt=new Set(["start","stop","restart","serve","run","status","install-service","uninstall-service"]);function zt(t){if(t.some(e=>e==="--application"||e.startsWith("--application=")))throw new Error("`--application` is no longer supported. ours-mcp connects to one coherently selected shared daemon; use OURS_CONFIG or a matching OURS_PORT + OURS_STATE_DIR selection.")}async function Xt(t){let n=(process.env.OURS_CLI??"").trim()||"ours";await new Promise((r,i)=>{let o=Gt(n,t,{stdio:"inherit",env:process.env});o.once("error",s=>{if(s.code==="ENOENT"){i(new Error(`Cannot find the ${JSON.stringify(n)} CLI. Install @ours.network/cli@2.7.2, put \`ours\` on PATH, or set OURS_CLI to its executable path.`));return}i(s)}),o.once("exit",(s,a)=>{if(a){process.kill(process.pid,a);return}process.exitCode=s??1,r()})})}async function Qt(){let t=new URL("./connector.js",import.meta.url),{runConnector:e}=await import(t.href);await e({leaseToken:C,clientPid:g,version:b,bindIdentity:Bt})}async function Zt(){let t=S(process.env);if(t!==null){let n;try{n=JSON.parse(Vt(0,"utf8"))}catch{throw new Error("SessionEnd requires valid hook JSON on stdin.")}let r=n?.session_id;if(typeof r!="string"||!r.trim())throw new Error("SessionEnd hook input must contain a non-empty session_id.");await G(t,r,process.env);return}await(await B({leaseToken:C,clientPid:g})).releaseLease()}function te(t,e){return JSON.stringify({identity:t,...e})}async function ee(t,e,n){for await(let r of t.watchNotifications(e,{kinds:["inbound"],signal:n}))c(te(e,r))}async function ne(t){if(t.length>1||t[0]?.startsWith("-"))throw new Error("Usage: ours-mcp watch [identity]");if(S(process.env)!==null)throw new Error("External owner context is required.");let e=Yt(),n=new f(e.expectStateDir);await n.list();let r=await B({leaseToken:C,clientPid:g}),i=t[0]?.trim(),o;i?o=[i]:o=(await $(n,await r.identities())).map(a=>a.name);let s=new AbortController;process.once("SIGINT",()=>s.abort()),process.once("SIGTERM",()=>s.abort()),K(`ours-mcp watch: ${o.length===0?"no application identities":`watching ${o.join(", ")}`}`),await Promise.all(o.map(a=>ee(r,a,s.signal)))}function re(){c(`ours-mcp ${b} \u2014 MCP adapter for the shared ours daemon`),c(""),c("Usage: ours-mcp <command> [options]"),c(" proxy run the stdio MCP server (never starts a daemon)"),c(" session-end release this harness session and clean up its temporary identities"),c(" watch [identity] stream inbound JSON Lines; without a name, only ours-mcp identities"),c(" start|stop|restart|serve|status"),c(" install-service|uninstall-service"),c(" compatibility aliases for `ours daemon <command>`"),c(" version print the ours-mcp package version"),c(""),c("Daemon configuration and identity CLI operations moved to @ours.network/cli@2.7.2:"),c(" ours config setup"),c(" ours identity --help")}async function ie(){let t=process.argv.slice(2);zt(t);let e=t.shift()??"help";if(Kt.has(e)){await Xt(["daemon",e==="run"?"serve":e,...t]);return}switch(e){case"proxy":if(t.length)throw new Error("Usage: ours-mcp proxy");await Qt();return;case"session-end":if(t.length)throw new Error("Usage: ours-mcp session-end");await Zt();return;case"watch":await ne(t);return;case"setup":throw new Error("ours-mcp no longer owns daemon configuration. Run `ours config setup` instead.");case"create-root":case"define-local-identity-file":case"voice-setup":case"voice-status":case"stt-setup":case"stt-status":throw new Error(`ours-mcp ${e} moved to the \`ours\` CLI. Run \`ours --help\` for the typed replacement.`);case"version":case"--version":case"-v":c(b);return;case"help":case"--help":case"-h":re();return;default:throw new Error(`Unknown command ${JSON.stringify(e)}. Run \`ours-mcp --help\`.`)}}function oe(){if(!process.argv[1])return!1;try{return V(process.argv[1])===V(Wt(import.meta.url))}catch{return!1}}var se=oe();se&&ie().catch(t=>{K(`ours-mcp error: ${t instanceof Error?t.message:String(t)}`),process.exitCode=1});
|
package/dist/connector.js
CHANGED
|
@@ -39,7 +39,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
39
39
|
deps: ${r}}`};var iI={keyword:"dependencies",type:"object",schemaType:"object",error:Pt.error,code(t){let[e,r]=aI(t);L_(t,e),F_(t,r)}};function aI({schema:t}){let e={},r={};for(let n in t){if(n==="__proto__")continue;let o=Array.isArray(t[n])?e:r;o[n]=t[n]}return[e,r]}function L_(t,e=t.schema){let{gen:r,data:n,it:o}=t;if(Object.keys(e).length===0)return;let s=r.let("missing");for(let i in e){let a=e[i];if(a.length===0)continue;let c=(0,Do.propertyInData)(r,n,i,o.opts.ownProperties);t.setParams({property:i,depsCount:a.length,deps:a.join(", ")}),o.allErrors?r.if(c,()=>{for(let u of a)(0,Do.checkReportMissingProp)(t,u)}):(r.if((0,np._)`${c} && (${(0,Do.checkMissingProp)(t,a,s)})`),(0,Do.reportMissingProp)(t,s),r.else())}}Pt.validatePropertyDeps=L_;function F_(t,e=t.schema){let{gen:r,data:n,keyword:o,it:s}=t,i=r.name("valid");for(let a in e)(0,sI.alwaysValidSchema)(s,e[a])||(r.if((0,Do.propertyInData)(r,n,a,s.opts.ownProperties),()=>{let c=t.subschema({keyword:o,schemaProp:a},i);t.mergeValidEvaluated(c,i)},()=>r.var(i,!0)),t.ok(i))}Pt.validateSchemaDeps=F_;Pt.default=iI});var H_=T(op=>{"use strict";Object.defineProperty(op,"__esModule",{value:!0});var V_=H(),cI=ee(),uI={message:"property name must be valid",params:({params:t})=>(0,V_._)`{propertyName: ${t.propertyName}}`},lI={keyword:"propertyNames",type:"object",schemaType:["object","boolean"],error:uI,code(t){let{gen:e,schema:r,data:n,it:o}=t;if((0,cI.alwaysValidSchema)(o,r))return;let s=e.name("valid");e.forIn("key",n,i=>{t.setParams({propertyName:i}),t.subschema({keyword:"propertyNames",data:i,dataTypes:["string"],propertyName:i,compositeRule:!0},s),e.if((0,V_.not)(s),()=>{t.error(!0),o.allErrors||e.break()})}),t.ok(s)}};op.default=lI});var ip=T(sp=>{"use strict";Object.defineProperty(sp,"__esModule",{value:!0});var Ai=ct(),_t=H(),dI=Mt(),Zi=ee(),pI={message:"must NOT have additional properties",params:({params:t})=>(0,_t._)`{additionalProperty: ${t.additionalProperty}}`},fI={keyword:"additionalProperties",type:["object"],schemaType:["boolean","object"],allowUndefined:!0,trackErrors:!0,error:pI,code(t){let{gen:e,schema:r,parentSchema:n,data:o,errsCount:s,it:i}=t;if(!s)throw new Error("ajv implementation error");let{allErrors:a,opts:c}=i;if(i.props=!0,c.removeAdditional!=="all"&&(0,Zi.alwaysValidSchema)(i,r))return;let u=(0,Ai.allSchemaProperties)(n.properties),l=(0,Ai.allSchemaProperties)(n.patternProperties);d(),t.ok((0,_t._)`${s} === ${dI.default.errors}`);function d(){e.forIn("key",o,g=>{!u.length&&!l.length?p(g):e.if(m(g),()=>p(g))})}function m(g){let b;if(u.length>8){let v=(0,Zi.schemaRefOrVal)(i,n.properties,"properties");b=(0,Ai.isOwnProperty)(e,v,g)}else u.length?b=(0,_t.or)(...u.map(v=>(0,_t._)`${g} === ${v}`)):b=_t.nil;return l.length&&(b=(0,_t.or)(b,...l.map(v=>(0,_t._)`${(0,Ai.usePattern)(t,v)}.test(${g})`))),(0,_t.not)(b)}function f(g){e.code((0,_t._)`delete ${o}[${g}]`)}function p(g){if(c.removeAdditional==="all"||c.removeAdditional&&r===!1){f(g);return}if(r===!1){t.setParams({additionalProperty:g}),t.error(),a||e.break();return}if(typeof r=="object"&&!(0,Zi.alwaysValidSchema)(i,r)){let b=e.name("valid");c.removeAdditional==="failing"?(h(g,b,!1),e.if((0,_t.not)(b),()=>{t.reset(),f(g)})):(h(g,b),a||e.if((0,_t.not)(b),()=>e.break()))}}function h(g,b,v){let k={keyword:"additionalProperties",dataProp:g,dataPropType:Zi.Type.Str};v===!1&&Object.assign(k,{compositeRule:!0,createErrors:!1,allErrors:!1}),t.subschema(k,b)}}};sp.default=fI});var G_=T(cp=>{"use strict";Object.defineProperty(cp,"__esModule",{value:!0});var mI=ko(),B_=ct(),ap=ee(),J_=ip(),hI={keyword:"properties",type:"object",schemaType:"object",code(t){let{gen:e,schema:r,parentSchema:n,data:o,it:s}=t;s.opts.removeAdditional==="all"&&n.additionalProperties===void 0&&J_.default.code(new mI.KeywordCxt(s,J_.default,"additionalProperties"));let i=(0,B_.allSchemaProperties)(r);for(let d of i)s.definedProperties.add(d);s.opts.unevaluated&&i.length&&s.props!==!0&&(s.props=ap.mergeEvaluated.props(e,(0,ap.toHash)(i),s.props));let a=i.filter(d=>!(0,ap.alwaysValidSchema)(s,r[d]));if(a.length===0)return;let c=e.name("valid");for(let d of a)u(d)?l(d):(e.if((0,B_.propertyInData)(e,o,d,s.opts.ownProperties)),l(d),s.allErrors||e.else().var(c,!0),e.endIf()),t.it.definedProperties.add(d),t.ok(c);function u(d){return s.opts.useDefaults&&!s.compositeRule&&r[d].default!==void 0}function l(d){t.subschema({keyword:"properties",schemaProp:d,dataProp:d},c)}}};cp.default=hI});var X_=T(up=>{"use strict";Object.defineProperty(up,"__esModule",{value:!0});var K_=ct(),ji=H(),W_=ee(),Y_=ee(),gI={keyword:"patternProperties",type:"object",schemaType:"object",code(t){let{gen:e,schema:r,data:n,parentSchema:o,it:s}=t,{opts:i}=s,a=(0,K_.allSchemaProperties)(r),c=a.filter(h=>(0,W_.alwaysValidSchema)(s,r[h]));if(a.length===0||c.length===a.length&&(!s.opts.unevaluated||s.props===!0))return;let u=i.strictSchema&&!i.allowMatchingProperties&&o.properties,l=e.name("valid");s.props!==!0&&!(s.props instanceof ji.Name)&&(s.props=(0,Y_.evaluatedPropsToName)(e,s.props));let{props:d}=s;m();function m(){for(let h of a)u&&f(h),s.allErrors?p(h):(e.var(l,!0),p(h),e.if(l))}function f(h){for(let g in u)new RegExp(h).test(g)&&(0,W_.checkStrictMode)(s,`property ${g} matches pattern ${h} (use allowMatchingProperties)`)}function p(h){e.forIn("key",n,g=>{e.if((0,ji._)`${(0,K_.usePattern)(t,h)}.test(${g})`,()=>{let b=c.includes(h);b||t.subschema({keyword:"patternProperties",schemaProp:h,dataProp:g,dataPropType:Y_.Type.Str},l),s.opts.unevaluated&&d!==!0?e.assign((0,ji._)`${d}[${g}]`,!0):!b&&!s.allErrors&&e.if((0,ji.not)(l),()=>e.break())})})}}};up.default=gI});var Q_=T(lp=>{"use strict";Object.defineProperty(lp,"__esModule",{value:!0});var yI=ee(),_I={keyword:"not",schemaType:["object","boolean"],trackErrors:!0,code(t){let{gen:e,schema:r,it:n}=t;if((0,yI.alwaysValidSchema)(n,r)){t.fail();return}let o=e.name("valid");t.subschema({keyword:"not",compositeRule:!0,createErrors:!1,allErrors:!1},o),t.failResult(o,()=>t.reset(),()=>t.error())},error:{message:"must NOT be valid"}};lp.default=_I});var ev=T(dp=>{"use strict";Object.defineProperty(dp,"__esModule",{value:!0});var vI=ct(),bI={keyword:"anyOf",schemaType:"array",trackErrors:!0,code:vI.validateUnion,error:{message:"must match a schema in anyOf"}};dp.default=bI});var tv=T(pp=>{"use strict";Object.defineProperty(pp,"__esModule",{value:!0});var Mi=H(),xI=ee(),wI={message:"must match exactly one schema in oneOf",params:({params:t})=>(0,Mi._)`{passingSchemas: ${t.passing}}`},$I={keyword:"oneOf",schemaType:"array",trackErrors:!0,error:wI,code(t){let{gen:e,schema:r,parentSchema:n,it:o}=t;if(!Array.isArray(r))throw new Error("ajv implementation error");if(o.opts.discriminator&&n.discriminator)return;let s=r,i=e.let("valid",!1),a=e.let("passing",null),c=e.name("_valid");t.setParams({passing:a}),e.block(u),t.result(i,()=>t.reset(),()=>t.error(!0));function u(){s.forEach((l,d)=>{let m;(0,xI.alwaysValidSchema)(o,l)?e.var(c,!0):m=t.subschema({keyword:"oneOf",schemaProp:d,compositeRule:!0},c),d>0&&e.if((0,Mi._)`${c} && ${i}`).assign(i,!1).assign(a,(0,Mi._)`[${a}, ${d}]`).else(),e.if(c,()=>{e.assign(i,!0),e.assign(a,d),m&&t.mergeEvaluated(m,Mi.Name)})})}}};pp.default=$I});var rv=T(fp=>{"use strict";Object.defineProperty(fp,"__esModule",{value:!0});var kI=ee(),SI={keyword:"allOf",schemaType:"array",code(t){let{gen:e,schema:r,it:n}=t;if(!Array.isArray(r))throw new Error("ajv implementation error");let o=e.name("valid");r.forEach((s,i)=>{if((0,kI.alwaysValidSchema)(n,s))return;let a=t.subschema({keyword:"allOf",schemaProp:i},o);t.ok(o),t.mergeEvaluated(a)})}};fp.default=SI});var sv=T(mp=>{"use strict";Object.defineProperty(mp,"__esModule",{value:!0});var Di=H(),ov=ee(),zI={message:({params:t})=>(0,Di.str)`must match "${t.ifClause}" schema`,params:({params:t})=>(0,Di._)`{failingKeyword: ${t.ifClause}}`},TI={keyword:"if",schemaType:["object","boolean"],trackErrors:!0,error:zI,code(t){let{gen:e,parentSchema:r,it:n}=t;r.then===void 0&&r.else===void 0&&(0,ov.checkStrictMode)(n,'"if" without "then" and "else" is ignored');let o=nv(n,"then"),s=nv(n,"else");if(!o&&!s)return;let i=e.let("valid",!0),a=e.name("_valid");if(c(),t.reset(),o&&s){let l=e.let("ifClause");t.setParams({ifClause:l}),e.if(a,u("then",l),u("else",l))}else o?e.if(a,u("then")):e.if((0,Di.not)(a),u("else"));t.pass(i,()=>t.error(!0));function c(){let l=t.subschema({keyword:"if",compositeRule:!0,createErrors:!1,allErrors:!1},a);t.mergeEvaluated(l)}function u(l,d){return()=>{let m=t.subschema({keyword:l},a);e.assign(i,a),t.mergeValidEvaluated(m,i),d?e.assign(d,(0,Di._)`${l}`):t.setParams({ifClause:l})}}}};function nv(t,e){let r=t.schema[e];return r!==void 0&&!(0,ov.alwaysValidSchema)(t,r)}mp.default=TI});var iv=T(hp=>{"use strict";Object.defineProperty(hp,"__esModule",{value:!0});var PI=ee(),EI={keyword:["then","else"],schemaType:["object","boolean"],code({keyword:t,parentSchema:e,it:r}){e.if===void 0&&(0,PI.checkStrictMode)(r,`"${t}" without "if" is ignored`)}};hp.default=EI});var av=T(gp=>{"use strict";Object.defineProperty(gp,"__esModule",{value:!0});var II=Xd(),RI=j_(),OI=Qd(),NI=D_(),CI=q_(),AI=U_(),ZI=H_(),jI=ip(),MI=G_(),DI=X_(),qI=Q_(),LI=ev(),FI=tv(),UI=rv(),VI=sv(),HI=iv();function BI(t=!1){let e=[qI.default,LI.default,FI.default,UI.default,VI.default,HI.default,ZI.default,jI.default,AI.default,MI.default,DI.default];return t?e.push(RI.default,NI.default):e.push(II.default,OI.default),e.push(CI.default),e}gp.default=BI});var cv=T(yp=>{"use strict";Object.defineProperty(yp,"__esModule",{value:!0});var _e=H(),JI={message:({schemaCode:t})=>(0,_e.str)`must match format "${t}"`,params:({schemaCode:t})=>(0,_e._)`{format: ${t}}`},GI={keyword:"format",type:["number","string"],schemaType:"string",$data:!0,error:JI,code(t,e){let{gen:r,data:n,$data:o,schema:s,schemaCode:i,it:a}=t,{opts:c,errSchemaPath:u,schemaEnv:l,self:d}=a;if(!c.validateFormats)return;o?m():f();function m(){let p=r.scopeValue("formats",{ref:d.formats,code:c.code.formats}),h=r.const("fDef",(0,_e._)`${p}[${i}]`),g=r.let("fType"),b=r.let("format");r.if((0,_e._)`typeof ${h} == "object" && !(${h} instanceof RegExp)`,()=>r.assign(g,(0,_e._)`${h}.type || "string"`).assign(b,(0,_e._)`${h}.validate`),()=>r.assign(g,(0,_e._)`"string"`).assign(b,h)),t.fail$data((0,_e.or)(v(),k()));function v(){return c.strictSchema===!1?_e.nil:(0,_e._)`${i} && !${b}`}function k(){let I=l.$async?(0,_e._)`(${h}.async ? await ${b}(${n}) : ${b}(${n}))`:(0,_e._)`${b}(${n})`,Z=(0,_e._)`(typeof ${b} == "function" ? ${I} : ${b}.test(${n}))`;return(0,_e._)`${b} && ${b} !== true && ${g} === ${e} && !${Z}`}}function f(){let p=d.formats[s];if(!p){v();return}if(p===!0)return;let[h,g,b]=k(p);h===e&&t.pass(I());function v(){if(c.strictSchema===!1){d.logger.warn(Z());return}throw new Error(Z());function Z(){return`unknown format "${s}" ignored in schema at path "${u}"`}}function k(Z){let Ce=Z instanceof RegExp?(0,_e.regexpCode)(Z):c.code.formats?(0,_e._)`${c.code.formats}${(0,_e.getProperty)(s)}`:void 0,et=r.scopeValue("formats",{key:s,ref:Z,code:Ce});return typeof Z=="object"&&!(Z instanceof RegExp)?[Z.type||"string",Z.validate,(0,_e._)`${et}.validate`]:["string",Z,et]}function I(){if(typeof p=="object"&&!(p instanceof RegExp)&&p.async){if(!l.$async)throw new Error("async format in sync schema");return(0,_e._)`await ${b}(${n})`}return typeof g=="function"?(0,_e._)`${b}(${n})`:(0,_e._)`${b}.test(${n})`}}}};yp.default=GI});var uv=T(_p=>{"use strict";Object.defineProperty(_p,"__esModule",{value:!0});var KI=cv(),WI=[KI.default];_p.default=WI});var lv=T($n=>{"use strict";Object.defineProperty($n,"__esModule",{value:!0});$n.contentVocabulary=$n.metadataVocabulary=void 0;$n.metadataVocabulary=["title","description","default","deprecated","readOnly","writeOnly","examples"];$n.contentVocabulary=["contentMediaType","contentEncoding","contentSchema"]});var pv=T(vp=>{"use strict";Object.defineProperty(vp,"__esModule",{value:!0});var YI=v_(),XI=N_(),QI=av(),eR=uv(),dv=lv(),tR=[YI.default,XI.default,(0,QI.default)(),eR.default,dv.metadataVocabulary,dv.contentVocabulary];vp.default=tR});var mv=T(qi=>{"use strict";Object.defineProperty(qi,"__esModule",{value:!0});qi.DiscrError=void 0;var fv;(function(t){t.Tag="tag",t.Mapping="mapping"})(fv||(qi.DiscrError=fv={}))});var gv=T(xp=>{"use strict";Object.defineProperty(xp,"__esModule",{value:!0});var kn=H(),bp=mv(),hv=xi(),rR=So(),nR=ee(),oR={message:({params:{discrError:t,tagName:e}})=>t===bp.DiscrError.Tag?`tag "${e}" must be string`:`value of tag "${e}" must be in oneOf`,params:({params:{discrError:t,tag:e,tagName:r}})=>(0,kn._)`{error: ${t}, tag: ${r}, tagValue: ${e}}`},sR={keyword:"discriminator",type:"object",schemaType:"object",error:oR,code(t){let{gen:e,data:r,schema:n,parentSchema:o,it:s}=t,{oneOf:i}=o;if(!s.opts.discriminator)throw new Error("discriminator: requires discriminator option");let a=n.propertyName;if(typeof a!="string")throw new Error("discriminator: requires propertyName");if(n.mapping)throw new Error("discriminator: mapping is not supported");if(!i)throw new Error("discriminator: requires oneOf keyword");let c=e.let("valid",!1),u=e.const("tag",(0,kn._)`${r}${(0,kn.getProperty)(a)}`);e.if((0,kn._)`typeof ${u} == "string"`,()=>l(),()=>t.error(!1,{discrError:bp.DiscrError.Tag,tag:u,tagName:a})),t.ok(c);function l(){let f=m();e.if(!1);for(let p in f)e.elseIf((0,kn._)`${u} === ${p}`),e.assign(c,d(f[p]));e.else(),t.error(!1,{discrError:bp.DiscrError.Mapping,tag:u,tagName:a}),e.endIf()}function d(f){let p=e.name("valid"),h=t.subschema({keyword:"oneOf",schemaProp:f},p);return t.mergeEvaluated(h,kn.Name),p}function m(){var f;let p={},h=b(o),g=!0;for(let I=0;I<i.length;I++){let Z=i[I];if(Z?.$ref&&!(0,nR.schemaHasRulesButRef)(Z,s.self.RULES)){let et=Z.$ref;if(Z=hv.resolveRef.call(s.self,s.schemaEnv.root,s.baseId,et),Z instanceof hv.SchemaEnv&&(Z=Z.schema),Z===void 0)throw new rR.default(s.opts.uriResolver,s.baseId,et)}let Ce=(f=Z?.properties)===null||f===void 0?void 0:f[a];if(typeof Ce!="object")throw new Error(`discriminator: oneOf subschemas (or referenced schemas) must have "properties/${a}"`);g=g&&(h||b(Z)),v(Ce,I)}if(!g)throw new Error(`discriminator: "${a}" must be required`);return p;function b({required:I}){return Array.isArray(I)&&I.includes(a)}function v(I,Z){if(I.const)k(I.const,Z);else if(I.enum)for(let Ce of I.enum)k(Ce,Z);else throw new Error(`discriminator: "properties/${a}" must have "const" or "enum"`)}function k(I,Z){if(typeof I!="string"||I in p)throw new Error(`discriminator: "${a}" values must be unique strings`);p[I]=Z}}}};xp.default=sR});var yv=T((iM,iR)=>{iR.exports={$schema:"http://json-schema.org/draft-07/schema#",$id:"http://json-schema.org/draft-07/schema#",title:"Core schema meta-schema",definitions:{schemaArray:{type:"array",minItems:1,items:{$ref:"#"}},nonNegativeInteger:{type:"integer",minimum:0},nonNegativeIntegerDefault0:{allOf:[{$ref:"#/definitions/nonNegativeInteger"},{default:0}]},simpleTypes:{enum:["array","boolean","integer","null","number","object","string"]},stringArray:{type:"array",items:{type:"string"},uniqueItems:!0,default:[]}},type:["object","boolean"],properties:{$id:{type:"string",format:"uri-reference"},$schema:{type:"string",format:"uri"},$ref:{type:"string",format:"uri-reference"},$comment:{type:"string"},title:{type:"string"},description:{type:"string"},default:!0,readOnly:{type:"boolean",default:!1},examples:{type:"array",items:!0},multipleOf:{type:"number",exclusiveMinimum:0},maximum:{type:"number"},exclusiveMaximum:{type:"number"},minimum:{type:"number"},exclusiveMinimum:{type:"number"},maxLength:{$ref:"#/definitions/nonNegativeInteger"},minLength:{$ref:"#/definitions/nonNegativeIntegerDefault0"},pattern:{type:"string",format:"regex"},additionalItems:{$ref:"#"},items:{anyOf:[{$ref:"#"},{$ref:"#/definitions/schemaArray"}],default:!0},maxItems:{$ref:"#/definitions/nonNegativeInteger"},minItems:{$ref:"#/definitions/nonNegativeIntegerDefault0"},uniqueItems:{type:"boolean",default:!1},contains:{$ref:"#"},maxProperties:{$ref:"#/definitions/nonNegativeInteger"},minProperties:{$ref:"#/definitions/nonNegativeIntegerDefault0"},required:{$ref:"#/definitions/stringArray"},additionalProperties:{$ref:"#"},definitions:{type:"object",additionalProperties:{$ref:"#"},default:{}},properties:{type:"object",additionalProperties:{$ref:"#"},default:{}},patternProperties:{type:"object",additionalProperties:{$ref:"#"},propertyNames:{format:"regex"},default:{}},dependencies:{type:"object",additionalProperties:{anyOf:[{$ref:"#"},{$ref:"#/definitions/stringArray"}]}},propertyNames:{$ref:"#"},const:!0,enum:{type:"array",items:!0,minItems:1,uniqueItems:!0},type:{anyOf:[{$ref:"#/definitions/simpleTypes"},{type:"array",items:{$ref:"#/definitions/simpleTypes"},minItems:1,uniqueItems:!0}]},format:{type:"string"},contentMediaType:{type:"string"},contentEncoding:{type:"string"},if:{$ref:"#"},then:{$ref:"#"},else:{$ref:"#"},allOf:{$ref:"#/definitions/schemaArray"},anyOf:{$ref:"#/definitions/schemaArray"},oneOf:{$ref:"#/definitions/schemaArray"},not:{$ref:"#"}},default:!0}});var $p=T((pe,wp)=>{"use strict";Object.defineProperty(pe,"__esModule",{value:!0});pe.MissingRefError=pe.ValidationError=pe.CodeGen=pe.Name=pe.nil=pe.stringify=pe.str=pe._=pe.KeywordCxt=pe.Ajv=void 0;var aR=f_(),cR=pv(),uR=gv(),_v=yv(),lR=["/properties"],Li="http://json-schema.org/draft-07/schema",Sn=class extends aR.default{_addVocabularies(){super._addVocabularies(),cR.default.forEach(e=>this.addVocabulary(e)),this.opts.discriminator&&this.addKeyword(uR.default)}_addDefaultMetaSchema(){if(super._addDefaultMetaSchema(),!this.opts.meta)return;let e=this.opts.$data?this.$dataMetaSchema(_v,lR):_v;this.addMetaSchema(e,Li,!1),this.refs["http://json-schema.org/schema"]=Li}defaultMeta(){return this.opts.defaultMeta=super.defaultMeta()||(this.getSchema(Li)?Li:void 0)}};pe.Ajv=Sn;wp.exports=pe=Sn;wp.exports.Ajv=Sn;Object.defineProperty(pe,"__esModule",{value:!0});pe.default=Sn;var dR=ko();Object.defineProperty(pe,"KeywordCxt",{enumerable:!0,get:function(){return dR.KeywordCxt}});var zn=H();Object.defineProperty(pe,"_",{enumerable:!0,get:function(){return zn._}});Object.defineProperty(pe,"str",{enumerable:!0,get:function(){return zn.str}});Object.defineProperty(pe,"stringify",{enumerable:!0,get:function(){return zn.stringify}});Object.defineProperty(pe,"nil",{enumerable:!0,get:function(){return zn.nil}});Object.defineProperty(pe,"Name",{enumerable:!0,get:function(){return zn.Name}});Object.defineProperty(pe,"CodeGen",{enumerable:!0,get:function(){return zn.CodeGen}});var pR=vi();Object.defineProperty(pe,"ValidationError",{enumerable:!0,get:function(){return pR.default}});var fR=So();Object.defineProperty(pe,"MissingRefError",{enumerable:!0,get:function(){return fR.default}})});var zv=T(It=>{"use strict";Object.defineProperty(It,"__esModule",{value:!0});It.formatNames=It.fastFormats=It.fullFormats=void 0;function Et(t,e){return{validate:t,compare:e}}It.fullFormats={date:Et(wv,Tp),time:Et(Sp(!0),Pp),"date-time":Et(vv(!0),kv),"iso-time":Et(Sp(),$v),"iso-date-time":Et(vv(),Sv),duration:/^P(?!$)((\d+Y)?(\d+M)?(\d+D)?(T(?=\d)(\d+H)?(\d+M)?(\d+S)?)?|(\d+W)?)$/,uri:vR,"uri-reference":/^(?:[a-z][a-z0-9+\-.]*:)?(?:\/?\/(?:(?:[a-z0-9\-._~!$&'()*+,;=:]|%[0-9a-f]{2})*@)?(?:\[(?:(?:(?:(?:[0-9a-f]{1,4}:){6}|::(?:[0-9a-f]{1,4}:){5}|(?:[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){4}|(?:(?:[0-9a-f]{1,4}:){0,1}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){3}|(?:(?:[0-9a-f]{1,4}:){0,2}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){2}|(?:(?:[0-9a-f]{1,4}:){0,3}[0-9a-f]{1,4})?::[0-9a-f]{1,4}:|(?:(?:[0-9a-f]{1,4}:){0,4}[0-9a-f]{1,4})?::)(?:[0-9a-f]{1,4}:[0-9a-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?))|(?:(?:[0-9a-f]{1,4}:){0,5}[0-9a-f]{1,4})?::[0-9a-f]{1,4}|(?:(?:[0-9a-f]{1,4}:){0,6}[0-9a-f]{1,4})?::)|[Vv][0-9a-f]+\.[a-z0-9\-._~!$&'()*+,;=:]+)\]|(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)|(?:[a-z0-9\-._~!$&'"()*+,;=]|%[0-9a-f]{2})*)(?::\d*)?(?:\/(?:[a-z0-9\-._~!$&'"()*+,;=:@]|%[0-9a-f]{2})*)*|\/(?:(?:[a-z0-9\-._~!$&'"()*+,;=:@]|%[0-9a-f]{2})+(?:\/(?:[a-z0-9\-._~!$&'"()*+,;=:@]|%[0-9a-f]{2})*)*)?|(?:[a-z0-9\-._~!$&'"()*+,;=:@]|%[0-9a-f]{2})+(?:\/(?:[a-z0-9\-._~!$&'"()*+,;=:@]|%[0-9a-f]{2})*)*)?(?:\?(?:[a-z0-9\-._~!$&'"()*+,;=:@/?]|%[0-9a-f]{2})*)?(?:#(?:[a-z0-9\-._~!$&'"()*+,;=:@/?]|%[0-9a-f]{2})*)?$/i,"uri-template":/^(?:(?:[^\x00-\x20"'<>%\\^`{|}]|%[0-9a-f]{2})|\{[+#./;?&=,!@|]?(?:[a-z0-9_]|%[0-9a-f]{2})+(?::[1-9][0-9]{0,3}|\*)?(?:,(?:[a-z0-9_]|%[0-9a-f]{2})+(?::[1-9][0-9]{0,3}|\*)?)*\})*$/i,url:/^(?:https?|ftp):\/\/(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z0-9\u{00a1}-\u{ffff}]+-)*[a-z0-9\u{00a1}-\u{ffff}]+)(?:\.(?:[a-z0-9\u{00a1}-\u{ffff}]+-)*[a-z0-9\u{00a1}-\u{ffff}]+)*(?:\.(?:[a-z\u{00a1}-\u{ffff}]{2,})))(?::\d{2,5})?(?:\/[^\s]*)?$/iu,email:/^[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/i,hostname:/^(?=.{1,253}\.?$)[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:\.[a-z0-9](?:[-0-9a-z]{0,61}[0-9a-z])?)*\.?$/i,ipv4:/^(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)$/,ipv6:/^((([0-9a-f]{1,4}:){7}([0-9a-f]{1,4}|:))|(([0-9a-f]{1,4}:){6}(:[0-9a-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9a-f]{1,4}:){5}(((:[0-9a-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9a-f]{1,4}:){4}(((:[0-9a-f]{1,4}){1,3})|((:[0-9a-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9a-f]{1,4}:){3}(((:[0-9a-f]{1,4}){1,4})|((:[0-9a-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9a-f]{1,4}:){2}(((:[0-9a-f]{1,4}){1,5})|((:[0-9a-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9a-f]{1,4}:){1}(((:[0-9a-f]{1,4}){1,6})|((:[0-9a-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9a-f]{1,4}){1,7})|((:[0-9a-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))$/i,regex:zR,uuid:/^(?:urn:uuid:)?[0-9a-f]{8}-(?:[0-9a-f]{4}-){3}[0-9a-f]{12}$/i,"json-pointer":/^(?:\/(?:[^~/]|~0|~1)*)*$/,"json-pointer-uri-fragment":/^#(?:\/(?:[a-z0-9_\-.!$&'()*+,;:=@]|%[0-9a-f]{2}|~0|~1)*)*$/i,"relative-json-pointer":/^(?:0|[1-9][0-9]*)(?:#|(?:\/(?:[^~/]|~0|~1)*)*)$/,byte:bR,int32:{type:"number",validate:$R},int64:{type:"number",validate:kR},float:{type:"number",validate:xv},double:{type:"number",validate:xv},password:!0,binary:!0};It.fastFormats={...It.fullFormats,date:Et(/^\d\d\d\d-[0-1]\d-[0-3]\d$/,Tp),time:Et(/^(?:[0-2]\d:[0-5]\d:[0-5]\d|23:59:60)(?:\.\d+)?(?:z|[+-]\d\d(?::?\d\d)?)$/i,Pp),"date-time":Et(/^\d\d\d\d-[0-1]\d-[0-3]\dt(?:[0-2]\d:[0-5]\d:[0-5]\d|23:59:60)(?:\.\d+)?(?:z|[+-]\d\d(?::?\d\d)?)$/i,kv),"iso-time":Et(/^(?:[0-2]\d:[0-5]\d:[0-5]\d|23:59:60)(?:\.\d+)?(?:z|[+-]\d\d(?::?\d\d)?)?$/i,$v),"iso-date-time":Et(/^\d\d\d\d-[0-1]\d-[0-3]\d[t\s](?:[0-2]\d:[0-5]\d:[0-5]\d|23:59:60)(?:\.\d+)?(?:z|[+-]\d\d(?::?\d\d)?)?$/i,Sv),uri:/^(?:[a-z][a-z0-9+\-.]*:)(?:\/?\/)?[^\s]*$/i,"uri-reference":/^(?:(?:[a-z][a-z0-9+\-.]*:)?\/?\/)?(?:[^\\\s#][^\s#]*)?(?:#[^\\\s]*)?$/i,email:/^[a-z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)*$/i};It.formatNames=Object.keys(It.fullFormats);function mR(t){return t%4===0&&(t%100!==0||t%400===0)}var hR=/^(\d\d\d\d)-(\d\d)-(\d\d)$/,gR=[0,31,28,31,30,31,30,31,31,30,31,30,31];function wv(t){let e=hR.exec(t);if(!e)return!1;let r=+e[1],n=+e[2],o=+e[3];return n>=1&&n<=12&&o>=1&&o<=(n===2&&mR(r)?29:gR[n])}function Tp(t,e){if(t&&e)return t>e?1:t<e?-1:0}var kp=/^(\d\d):(\d\d):(\d\d(?:\.\d+)?)(z|([+-])(\d\d)(?::?(\d\d))?)?$/i;function Sp(t){return function(r){let n=kp.exec(r);if(!n)return!1;let o=+n[1],s=+n[2],i=+n[3],a=n[4],c=n[5]==="-"?-1:1,u=+(n[6]||0),l=+(n[7]||0);if(u>23||l>59||t&&!a)return!1;if(o<=23&&s<=59&&i<60)return!0;let d=s-l*c,m=o-u*c-(d<0?1:0);return(m===23||m===-1)&&(d===59||d===-1)&&i<61}}function Pp(t,e){if(!(t&&e))return;let r=new Date("2020-01-01T"+t).valueOf(),n=new Date("2020-01-01T"+e).valueOf();if(r&&n)return r-n}function $v(t,e){if(!(t&&e))return;let r=kp.exec(t),n=kp.exec(e);if(r&&n)return t=r[1]+r[2]+r[3],e=n[1]+n[2]+n[3],t>e?1:t<e?-1:0}var zp=/t|\s/i;function vv(t){let e=Sp(t);return function(n){let o=n.split(zp);return o.length===2&&wv(o[0])&&e(o[1])}}function kv(t,e){if(!(t&&e))return;let r=new Date(t).valueOf(),n=new Date(e).valueOf();if(r&&n)return r-n}function Sv(t,e){if(!(t&&e))return;let[r,n]=t.split(zp),[o,s]=e.split(zp),i=Tp(r,o);if(i!==void 0)return i||Pp(n,s)}var yR=/\/|:/,_R=/^(?:[a-z][a-z0-9+\-.]*:)(?:\/?\/(?:(?:[a-z0-9\-._~!$&'()*+,;=:]|%[0-9a-f]{2})*@)?(?:\[(?:(?:(?:(?:[0-9a-f]{1,4}:){6}|::(?:[0-9a-f]{1,4}:){5}|(?:[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){4}|(?:(?:[0-9a-f]{1,4}:){0,1}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){3}|(?:(?:[0-9a-f]{1,4}:){0,2}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){2}|(?:(?:[0-9a-f]{1,4}:){0,3}[0-9a-f]{1,4})?::[0-9a-f]{1,4}:|(?:(?:[0-9a-f]{1,4}:){0,4}[0-9a-f]{1,4})?::)(?:[0-9a-f]{1,4}:[0-9a-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?))|(?:(?:[0-9a-f]{1,4}:){0,5}[0-9a-f]{1,4})?::[0-9a-f]{1,4}|(?:(?:[0-9a-f]{1,4}:){0,6}[0-9a-f]{1,4})?::)|[Vv][0-9a-f]+\.[a-z0-9\-._~!$&'()*+,;=:]+)\]|(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)|(?:[a-z0-9\-._~!$&'()*+,;=]|%[0-9a-f]{2})*)(?::\d*)?(?:\/(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})*)*|\/(?:(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})+(?:\/(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})*)*)?|(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})+(?:\/(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})*)*)(?:\?(?:[a-z0-9\-._~!$&'()*+,;=:@/?]|%[0-9a-f]{2})*)?(?:#(?:[a-z0-9\-._~!$&'()*+,;=:@/?]|%[0-9a-f]{2})*)?$/i;function vR(t){return yR.test(t)&&_R.test(t)}var bv=/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/gm;function bR(t){return bv.lastIndex=0,bv.test(t)}var xR=-(2**31),wR=2**31-1;function $R(t){return Number.isInteger(t)&&t<=wR&&t>=xR}function kR(t){return Number.isInteger(t)}function xv(){return!0}var SR=/[^\\]\\Z/;function zR(t){if(SR.test(t))return!1;try{return new RegExp(t),!0}catch{return!1}}});var Tv=T(Tn=>{"use strict";Object.defineProperty(Tn,"__esModule",{value:!0});Tn.formatLimitDefinition=void 0;var TR=$p(),vt=H(),ir=vt.operators,Fi={formatMaximum:{okStr:"<=",ok:ir.LTE,fail:ir.GT},formatMinimum:{okStr:">=",ok:ir.GTE,fail:ir.LT},formatExclusiveMaximum:{okStr:"<",ok:ir.LT,fail:ir.GTE},formatExclusiveMinimum:{okStr:">",ok:ir.GT,fail:ir.LTE}},PR={message:({keyword:t,schemaCode:e})=>(0,vt.str)`should be ${Fi[t].okStr} ${e}`,params:({keyword:t,schemaCode:e})=>(0,vt._)`{comparison: ${Fi[t].okStr}, limit: ${e}}`};Tn.formatLimitDefinition={keyword:Object.keys(Fi),type:"string",schemaType:"string",$data:!0,error:PR,code(t){let{gen:e,data:r,schemaCode:n,keyword:o,it:s}=t,{opts:i,self:a}=s;if(!i.validateFormats)return;let c=new TR.KeywordCxt(s,a.RULES.all.format.definition,"format");c.$data?u():l();function u(){let m=e.scopeValue("formats",{ref:a.formats,code:i.code.formats}),f=e.const("fmt",(0,vt._)`${m}[${c.schemaCode}]`);t.fail$data((0,vt.or)((0,vt._)`typeof ${f} != "object"`,(0,vt._)`${f} instanceof RegExp`,(0,vt._)`typeof ${f}.compare != "function"`,d(f)))}function l(){let m=c.schema,f=a.formats[m];if(!f||f===!0)return;if(typeof f!="object"||f instanceof RegExp||typeof f.compare!="function")throw new Error(`"${o}": format "${m}" does not define "compare" function`);let p=e.scopeValue("formats",{key:m,ref:f,code:i.code.formats?(0,vt._)`${i.code.formats}${(0,vt.getProperty)(m)}`:void 0});t.fail$data(d(p))}function d(m){return(0,vt._)`${m}.compare(${r}, ${n}) ${Fi[o].fail} 0`}},dependencies:["format"]};var ER=t=>(t.addKeyword(Tn.formatLimitDefinition),t);Tn.default=ER});var Rv=T((qo,Iv)=>{"use strict";Object.defineProperty(qo,"__esModule",{value:!0});var Pn=zv(),IR=Tv(),Ep=H(),Pv=new Ep.Name("fullFormats"),RR=new Ep.Name("fastFormats"),Ip=(t,e={keywords:!0})=>{if(Array.isArray(e))return Ev(t,e,Pn.fullFormats,Pv),t;let[r,n]=e.mode==="fast"?[Pn.fastFormats,RR]:[Pn.fullFormats,Pv],o=e.formats||Pn.formatNames;return Ev(t,o,r,n),e.keywords&&(0,IR.default)(t),t};Ip.get=(t,e="full")=>{let n=(e==="fast"?Pn.fastFormats:Pn.fullFormats)[t];if(!n)throw new Error(`Unknown format "${t}"`);return n};function Ev(t,e,r,n){var o,s;(o=(s=t.opts.code).formats)!==null&&o!==void 0||(s.formats=(0,Ep._)`require("ajv-formats/dist/formats").${n}`);for(let i of e)t.addFormat(i,r[i])}Iv.exports=qo=Ip;Object.defineProperty(qo,"__esModule",{value:!0});qo.default=Ip});function OR(){let t=new Ov.default({strict:!1,validateFormats:!0,validateSchema:!1,allErrors:!0});return(0,Nv.default)(t),t}var Ov,Nv,Ui,Cv=x(()=>{Ov=Hp($p(),1),Nv=Hp(Rv(),1);Ui=class{constructor(e){this._ajv=e??OR()}getValidator(e){let r="$id"in e&&typeof e.$id=="string"?this._ajv.getSchema(e.$id)??this._ajv.compile(e):this._ajv.compile(e);return n=>r(n)?{valid:!0,data:n,errorMessage:void 0}:{valid:!1,data:void 0,errorMessage:this._ajv.errorsText(r.errors)}}}});var Vi,Av=x(()=>{Qr();Vi=class{constructor(e){this._server=e}requestStream(e,r,n){return this._server.requestStream(e,r,n)}createMessageStream(e,r){let n=this._server.getClientCapabilities();if((e.tools||e.toolChoice)&&!n?.sampling?.tools)throw new Error("Client does not support sampling tools capability.");if(e.messages.length>0){let o=e.messages[e.messages.length-1],s=Array.isArray(o.content)?o.content:[o.content],i=s.some(l=>l.type==="tool_result"),a=e.messages.length>1?e.messages[e.messages.length-2]:void 0,c=a?Array.isArray(a.content)?a.content:[a.content]:[],u=c.some(l=>l.type==="tool_use");if(i){if(s.some(l=>l.type!=="tool_result"))throw new Error("The last message must contain only tool_result content if any is present");if(!u)throw new Error("tool_result blocks are not matching any tool_use from the previous message")}if(u){let l=new Set(c.filter(m=>m.type==="tool_use").map(m=>m.id)),d=new Set(s.filter(m=>m.type==="tool_result").map(m=>m.toolUseId));if(l.size!==d.size||![...l].every(m=>d.has(m)))throw new Error("ids of tool_result blocks and tool_use blocks from previous message do not match")}}return this.requestStream({method:"sampling/createMessage",params:e},Qn,r)}elicitInputStream(e,r){let n=this._server.getClientCapabilities(),o=e.mode??"form";switch(o){case"url":{if(!n?.elicitation?.url)throw new Error("Client does not support url elicitation.");break}case"form":{if(!n?.elicitation?.form)throw new Error("Client does not support form elicitation.");break}}let s=o==="form"&&e.mode===void 0?{...e,mode:"form"}:e;return this.requestStream({method:"elicitation/create",params:s},Xr,r)}async getTask(e,r){return this._server.getTask({taskId:e},r)}async getTaskResult(e,r,n){return this._server.getTaskResult({taskId:e},r,n)}async listTasks(e,r){return this._server.listTasks(e?{cursor:e}:void 0,r)}async cancelTask(e,r){return this._server.cancelTask({taskId:e},r)}}});function Zv(t,e,r){if(!t)throw new Error(`${r} does not support task creation (required for ${e})`);switch(e){case"tools/call":if(!t.tools?.call)throw new Error(`${r} does not support task creation for tools/call (required for ${e})`);break;default:break}}function jv(t,e,r){if(!t)throw new Error(`${r} does not support task creation (required for ${e})`);switch(e){case"sampling/createMessage":if(!t.sampling?.createMessage)throw new Error(`${r} does not support task creation for sampling/createMessage (required for ${e})`);break;case"elicitation/create":if(!t.elicitation?.create)throw new Error(`${r} does not support task creation for elicitation/create (required for ${e})`);break;default:break}}var Mv=x(()=>{});var Hi,Dv=x(()=>{Og();Qr();Cv();co();Av();Mv();Hi=class extends ii{constructor(e,r){super(r),this._serverInfo=e,this._loggingLevels=new Map,this.LOG_LEVEL_SEVERITY=new Map(Xn.options.map((n,o)=>[n,o])),this.isMessageIgnored=(n,o)=>{let s=this._loggingLevels.get(o);return s?this.LOG_LEVEL_SEVERITY.get(n)<this.LOG_LEVEL_SEVERITY.get(s):!1},this._capabilities=r?.capabilities??{},this._instructions=r?.instructions,this._jsonSchemaValidator=r?.jsonSchemaValidator??new Ui,this.setRequestHandler(ku,n=>this._oninitialize(n)),this.setNotificationHandler(Su,()=>this.oninitialized?.()),this._capabilities.logging&&this.setRequestHandler(Ou,async(n,o)=>{let s=o.sessionId||o.requestInfo?.headers["mcp-session-id"]||void 0,{level:i}=n.params,a=Xn.safeParse(i);return a.success&&this._loggingLevels.set(s,a.data),{}})}get experimental(){return this._experimental||(this._experimental={tasks:new Vi(this)}),this._experimental}registerCapabilities(e){if(this.transport)throw new Error("Cannot register capabilities after connecting to transport");this._capabilities=Rg(this._capabilities,e)}setRequestHandler(e,r){let o=Wt(e)?.method;if(!o)throw new Error("Schema is missing a method literal");let s;if(st(o)){let a=o;s=a._zod?.def?.value??a.value}else{let a=o;s=a._def?.value??a.value}if(typeof s!="string")throw new Error("Schema method literal must be a string");if(s==="tools/call"){let a=async(c,u)=>{let l=Kt(Yr,c);if(!l.success){let p=l.error instanceof Error?l.error.message:String(l.error);throw new O(A.InvalidParams,`Invalid tools/call request: ${p}`)}let{params:d}=l.data,m=await Promise.resolve(r(c,u));if(d.task){let p=Kt(Kr,m);if(!p.success){let h=p.error instanceof Error?p.error.message:String(p.error);throw new O(A.InvalidParams,`Invalid task creation result: ${h}`)}return p.data}let f=Kt(Ns,m);if(!f.success){let p=f.error instanceof Error?f.error.message:String(f.error);throw new O(A.InvalidParams,`Invalid tools/call result: ${p}`)}return f.data};return super.setRequestHandler(e,a)}return super.setRequestHandler(e,r)}assertCapabilityForMethod(e){switch(e){case"sampling/createMessage":if(!this._clientCapabilities?.sampling)throw new Error(`Client does not support sampling (required for ${e})`);break;case"elicitation/create":if(!this._clientCapabilities?.elicitation)throw new Error(`Client does not support elicitation (required for ${e})`);break;case"roots/list":if(!this._clientCapabilities?.roots)throw new Error(`Client does not support listing roots (required for ${e})`);break;case"ping":break}}assertNotificationCapability(e){switch(e){case"notifications/message":if(!this._capabilities.logging)throw new Error(`Server does not support logging (required for ${e})`);break;case"notifications/resources/updated":case"notifications/resources/list_changed":if(!this._capabilities.resources)throw new Error(`Server does not support notifying about resources (required for ${e})`);break;case"notifications/tools/list_changed":if(!this._capabilities.tools)throw new Error(`Server does not support notifying of tool list changes (required for ${e})`);break;case"notifications/prompts/list_changed":if(!this._capabilities.prompts)throw new Error(`Server does not support notifying of prompt list changes (required for ${e})`);break;case"notifications/elicitation/complete":if(!this._clientCapabilities?.elicitation?.url)throw new Error(`Client does not support URL elicitation (required for ${e})`);break;case"notifications/cancelled":break;case"notifications/progress":break}}assertRequestHandlerCapability(e){if(this._capabilities)switch(e){case"completion/complete":if(!this._capabilities.completions)throw new Error(`Server does not support completions (required for ${e})`);break;case"logging/setLevel":if(!this._capabilities.logging)throw new Error(`Server does not support logging (required for ${e})`);break;case"prompts/get":case"prompts/list":if(!this._capabilities.prompts)throw new Error(`Server does not support prompts (required for ${e})`);break;case"resources/list":case"resources/templates/list":case"resources/read":if(!this._capabilities.resources)throw new Error(`Server does not support resources (required for ${e})`);break;case"tools/call":case"tools/list":if(!this._capabilities.tools)throw new Error(`Server does not support tools (required for ${e})`);break;case"tasks/get":case"tasks/list":case"tasks/result":case"tasks/cancel":if(!this._capabilities.tasks)throw new Error(`Server does not support tasks capability (required for ${e})`);break;case"ping":case"initialize":break}}assertTaskCapability(e){jv(this._clientCapabilities?.tasks?.requests,e,"Client")}assertTaskHandlerCapability(e){this._capabilities&&Zv(this._capabilities.tasks?.requests,e,"Server")}async _oninitialize(e){let r=e.params.protocolVersion;return this._clientCapabilities=e.params.capabilities,this._clientVersion=e.params.clientInfo,{protocolVersion:Lm.includes(r)?r:vu,capabilities:this.getCapabilities(),serverInfo:this._serverInfo,...this._instructions&&{instructions:this._instructions}}}getClientCapabilities(){return this._clientCapabilities}getClientVersion(){return this._clientVersion}getCapabilities(){return this._capabilities}async ping(){return this.request({method:"ping"},ys)}async createMessage(e,r){if((e.tools||e.toolChoice)&&!this._clientCapabilities?.sampling?.tools)throw new Error("Client does not support sampling tools capability.");if(e.messages.length>0){let n=e.messages[e.messages.length-1],o=Array.isArray(n.content)?n.content:[n.content],s=o.some(u=>u.type==="tool_result"),i=e.messages.length>1?e.messages[e.messages.length-2]:void 0,a=i?Array.isArray(i.content)?i.content:[i.content]:[],c=a.some(u=>u.type==="tool_use");if(s){if(o.some(u=>u.type!=="tool_result"))throw new Error("The last message must contain only tool_result content if any is present");if(!c)throw new Error("tool_result blocks are not matching any tool_use from the previous message")}if(c){let u=new Set(a.filter(d=>d.type==="tool_use").map(d=>d.id)),l=new Set(o.filter(d=>d.type==="tool_result").map(d=>d.toolUseId));if(u.size!==l.size||![...u].every(d=>l.has(d)))throw new Error("ids of tool_result blocks and tool_use blocks from previous message do not match")}}return e.tools?this.request({method:"sampling/createMessage",params:e},Nu,r):this.request({method:"sampling/createMessage",params:e},Qn,r)}async elicitInput(e,r){switch(e.mode??"form"){case"url":{if(!this._clientCapabilities?.elicitation?.url)throw new Error("Client does not support url elicitation.");let o=e;return this.request({method:"elicitation/create",params:o},Xr,r)}case"form":{if(!this._clientCapabilities?.elicitation?.form)throw new Error("Client does not support form elicitation.");let o=e.mode==="form"?e:{...e,mode:"form"},s=await this.request({method:"elicitation/create",params:o},Xr,r);if(s.action==="accept"&&s.content&&o.requestedSchema)try{let a=this._jsonSchemaValidator.getValidator(o.requestedSchema)(s.content);if(!a.valid)throw new O(A.InvalidParams,`Elicitation response content does not match requested schema: ${a.errorMessage}`)}catch(i){throw i instanceof O?i:new O(A.InternalError,`Error validating elicitation response: ${i instanceof Error?i.message:String(i)}`)}return s}}}createElicitationCompletionNotifier(e,r){if(!this._clientCapabilities?.elicitation?.url)throw new Error("Client does not support URL elicitation (required for notifications/elicitation/complete)");return()=>this.notification({method:"notifications/elicitation/complete",params:{elicitationId:e}},r)}async listRoots(e,r){return this.request({method:"roots/list",params:e},Cu,r)}async sendLoggingMessage(e,r){if(this._capabilities.logging&&!this.isMessageIgnored(e.level,r))return this.notification({method:"notifications/message",params:e})}async sendResourceUpdated(e){return this.notification({method:"notifications/resources/updated",params:e})}async sendResourceListChanged(){return this.notification({method:"notifications/resources/list_changed"})}async sendToolListChanged(){return this.notification({method:"notifications/tools/list_changed"})}async sendPromptListChanged(){return this.notification({method:"notifications/prompts/list_changed"})}}});function Rp(t){return!!t&&typeof t=="object"&&Lv in t}function Fv(t){return t[Lv]?.complete}var Lv,qv,Uv=x(()=>{Lv=Symbol.for("mcp.completable");(function(t){t.Completable="McpCompletable"})(qv||(qv={}))});var Bi,Vv=x(()=>{Bi=class t{static isTemplate(e){return/\{[^}\s]+\}/.test(e)}static validateLength(e,r,n){if(e.length>r)throw new Error(`${n} exceeds maximum length of ${r} characters (got ${e.length})`)}get variableNames(){return this.parts.flatMap(e=>typeof e=="string"?[]:e.names)}constructor(e){t.validateLength(e,1e6,"Template"),this.template=e,this.parts=this.parse(e)}toString(){return this.template}parse(e){let r=[],n="",o=0,s=0;for(;o<e.length;)if(e[o]==="{"){n&&(r.push(n),n="");let i=e.indexOf("}",o);if(i===-1)throw new Error("Unclosed template expression");if(s++,s>1e4)throw new Error("Template contains too many expressions (max 10000)");let a=e.slice(o+1,i),c=this.getOperator(a),u=a.includes("*"),l=this.getNames(a),d=l[0];for(let m of l)t.validateLength(m,1e6,"Variable name");r.push({name:d,operator:c,names:l,exploded:u}),o=i+1}else n+=e[o],o++;return n&&r.push(n),r}getOperator(e){return["+","#",".","/","?","&"].find(n=>e.startsWith(n))||""}getNames(e){let r=this.getOperator(e);return e.slice(r.length).split(",").map(n=>n.replace("*","").trim()).filter(n=>n.length>0)}encodeValue(e,r){return t.validateLength(e,1e6,"Variable value"),r==="+"||r==="#"?encodeURI(e):encodeURIComponent(e)}expandPart(e,r){if(e.operator==="?"||e.operator==="&"){let i=e.names.map(c=>{let u=r[c];if(u===void 0)return"";let l=Array.isArray(u)?u.map(d=>this.encodeValue(d,e.operator)).join(","):this.encodeValue(u.toString(),e.operator);return`${c}=${l}`}).filter(c=>c.length>0);return i.length===0?"":(e.operator==="?"?"?":"&")+i.join("&")}if(e.names.length>1){let i=e.names.map(a=>r[a]).filter(a=>a!==void 0);return i.length===0?"":i.map(a=>Array.isArray(a)?a[0]:a).join(",")}let n=r[e.name];if(n===void 0)return"";let s=(Array.isArray(n)?n:[n]).map(i=>this.encodeValue(i,e.operator));switch(e.operator){case"":return s.join(",");case"+":return s.join(",");case"#":return"#"+s.join(",");case".":return"."+s.join(".");case"/":return"/"+s.join("/");default:return s.join(",")}}expand(e){let r="",n=!1;for(let o of this.parts){if(typeof o=="string"){r+=o;continue}let s=this.expandPart(o,e);s&&((o.operator==="?"||o.operator==="&")&&n?r+=s.replace("?","&"):r+=s,(o.operator==="?"||o.operator==="&")&&(n=!0))}return r}escapeRegExp(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}partToRegExp(e){let r=[];for(let s of e.names)t.validateLength(s,1e6,"Variable name");if(e.operator==="?"||e.operator==="&"){for(let s=0;s<e.names.length;s++){let i=e.names[s],a=s===0?"\\"+e.operator:"&";r.push({pattern:a+this.escapeRegExp(i)+"=([^&]+)",name:i})}return r}let n,o=e.name;switch(e.operator){case"":n=e.exploded?"([^/,]+(?:,[^/,]+)*)":"([^/,]+)";break;case"+":case"#":n="(.+)";break;case".":n="\\.([^/,]+)";break;case"/":n="/"+(e.exploded?"([^/,]+(?:,[^/,]+)*)":"([^/,]+)");break;default:n="([^/]+)"}return r.push({pattern:n,name:o}),r}match(e){t.validateLength(e,1e6,"URI");let r="^",n=[];for(let a of this.parts)if(typeof a=="string")r+=this.escapeRegExp(a);else{let c=this.partToRegExp(a);for(let{pattern:u,name:l}of c)r+=u,n.push({name:l,exploded:a.exploded})}r+="$",t.validateLength(r,1e6,"Generated regex pattern");let o=new RegExp(r),s=e.match(o);if(!s)return null;let i={};for(let a=0;a<n.length;a++){let{name:c,exploded:u}=n[a],l=s[a+1],d=c.replace("*","");u&&l.includes(",")?i[d]=l.split(","):i[d]=l}return i}}});function CR(t){let e=[];if(t.length===0)return{isValid:!1,warnings:["Tool name cannot be empty"]};if(t.length>128)return{isValid:!1,warnings:[`Tool name exceeds maximum length of 128 characters (current: ${t.length})`]};if(t.includes(" ")&&e.push("Tool name contains spaces, which may cause parsing issues"),t.includes(",")&&e.push("Tool name contains commas, which may cause parsing issues"),(t.startsWith("-")||t.endsWith("-"))&&e.push("Tool name starts or ends with a dash, which may cause parsing issues in some contexts"),(t.startsWith(".")||t.endsWith("."))&&e.push("Tool name starts or ends with a dot, which may cause parsing issues in some contexts"),!NR.test(t)){let r=t.split("").filter(n=>!/[A-Za-z0-9._-]/.test(n)).filter((n,o,s)=>s.indexOf(n)===o);return e.push(`Tool name contains invalid characters: ${r.map(n=>`"${n}"`).join(", ")}`,"Allowed characters are: A-Z, a-z, 0-9, underscore (_), dash (-), and dot (.)"),{isValid:!1,warnings:e}}return{isValid:!0,warnings:e}}function AR(t,e){if(e.length>0){console.warn(`Tool name validation warning for "${t}":`);for(let r of e)console.warn(` - ${r}`);console.warn("Tool registration will proceed, but this may cause compatibility issues."),console.warn("Consider updating the tool name to conform to the MCP tool naming standard."),console.warn("See SEP: Specify Format for Tool Names (https://github.com/modelcontextprotocol/modelcontextprotocol/issues/986) for more details.")}}function Op(t){let e=CR(t);return AR(t,e.warnings),e.isValid}var NR,Hv=x(()=>{NR=/^[A-Za-z0-9._-]{1,128}$/});var Ji,Bv=x(()=>{Ji=class{constructor(e){this._mcpServer=e}registerToolTask(e,r,n){let o={taskSupport:"required",...r.execution};if(o.taskSupport==="forbidden")throw new Error(`Cannot register task-based tool '${e}' with taskSupport 'forbidden'. Use registerTool() instead.`);return this._mcpServer._createRegisteredTool(e,r.title,r.description,r.inputSchema,r.outputSchema,r.annotations,o,r._meta,n)}}});var qt=x(()=>{Bs();Bs()});var Yv={};Vo(Yv,{McpServer:()=>Fo,ResourceTemplate:()=>Np});function Kv(t){return t!==null&&typeof t=="object"&&"parse"in t&&typeof t.parse=="function"&&"safeParse"in t&&typeof t.safeParse=="function"}function Wv(t){return"_def"in t||"_zod"in t||Kv(t)}function Cp(t){return typeof t!="object"||t===null||Wv(t)?!1:Object.keys(t).length===0?!0:Object.values(t).some(Kv)}function Jv(t){if(t){if(Cp(t))return Ir(t);if(!Wv(t))throw new Error("inputSchema must be a Zod schema or raw shape, received an unrecognized object");return t}}function jR(t){let e=Wt(t);return e?Object.entries(e).map(([r,n])=>{let o=Jh(n),s=Gh(n);return{name:r,description:o,required:!s}}):[]}function ar(t){let r=Wt(t)?.method;if(!r)throw new Error("Schema is missing a method literal");let n=Ks(r);if(typeof n=="string")return n;throw new Error("Schema method literal must be a string")}function Gv(t){return{completion:{values:t.slice(0,100),total:t.length,hasMore:t.length>100}}}var Fo,Np,ZR,Lo,Ap=x(()=>{Dv();co();Nl();Qr();Uv();Vv();Hv();Bv();qt();Fo=class{constructor(e,r){this._registeredResources={},this._registeredResourceTemplates={},this._registeredTools={},this._registeredPrompts={},this._toolHandlersInitialized=!1,this._completionHandlerInitialized=!1,this._resourceHandlersInitialized=!1,this._promptHandlersInitialized=!1,this.server=new Hi(e,r)}get experimental(){return this._experimental||(this._experimental={tasks:new Ji(this)}),this._experimental}async connect(e){return await this.server.connect(e)}async close(){await this.server.close()}setToolRequestHandlers(){this._toolHandlersInitialized||(this.server.assertCanSetRequestHandler(ar(Os)),this.server.assertCanSetRequestHandler(ar(Yr)),this.server.registerCapabilities({tools:{listChanged:!0}}),this.server.setRequestHandler(Os,()=>({tools:Object.entries(this._registeredTools).filter(([,e])=>e.enabled).map(([e,r])=>{let n={name:e,title:r.title,description:r.description,inputSchema:(()=>{let o=dn(r.inputSchema);return o?Il(o,{strictUnions:!0,pipeStrategy:"input"}):ZR})(),annotations:r.annotations,execution:r.execution,_meta:r._meta};if(r.outputSchema){let o=dn(r.outputSchema);o&&(n.outputSchema=Il(o,{strictUnions:!0,pipeStrategy:"output"}))}return n})})),this.server.setRequestHandler(Yr,async(e,r)=>{try{let n=this._registeredTools[e.params.name];if(!n)throw new O(A.InvalidParams,`Tool ${e.params.name} not found`);if(!n.enabled)throw new O(A.InvalidParams,`Tool ${e.params.name} disabled`);let o=!!e.params.task,s=n.execution?.taskSupport,i="createTask"in n.handler;if((s==="required"||s==="optional")&&!i)throw new O(A.InternalError,`Tool ${e.params.name} has taskSupport '${s}' but was not registered with registerToolTask`);if(s==="required"&&!o)throw new O(A.MethodNotFound,`Tool ${e.params.name} requires task augmentation (taskSupport: 'required')`);if(s==="optional"&&!o&&i)return await this.handleAutomaticTaskPolling(n,e,r);let a=await this.validateToolInput(n,e.params.arguments,e.params.name),c=await this.executeToolHandler(n,a,r);return o||await this.validateToolOutput(n,c,e.params.name),c}catch(n){if(n instanceof O&&n.code===A.UrlElicitationRequired)throw n;return this.createToolError(n instanceof Error?n.message:String(n))}}),this._toolHandlersInitialized=!0)}createToolError(e){return{content:[{type:"text",text:e}],isError:!0}}async validateToolInput(e,r,n){if(!e.inputSchema)return;let s=dn(e.inputSchema)??e.inputSchema,i=await Js(s,r);if(!i.success){let a="error"in i?i.error:"Unknown error",c=Gs(a);throw new O(A.InvalidParams,`Input validation error: Invalid arguments for tool ${n}: ${c}`)}return i.data}async validateToolOutput(e,r,n){if(!e.outputSchema||!("content"in r)||r.isError)return;if(!r.structuredContent)throw new O(A.InvalidParams,`Output validation error: Tool ${n} has an output schema but no structured content was provided`);let o=dn(e.outputSchema),s=await Js(o,r.structuredContent);if(!s.success){let i="error"in s?s.error:"Unknown error",a=Gs(i);throw new O(A.InvalidParams,`Output validation error: Invalid structured content for tool ${n}: ${a}`)}}async executeToolHandler(e,r,n){let o=e.handler;if("createTask"in o){if(!n.taskStore)throw new Error("No task store provided.");let i={...n,taskStore:n.taskStore};if(e.inputSchema){let a=o;return await Promise.resolve(a.createTask(r,i))}else{let a=o;return await Promise.resolve(a.createTask(i))}}if(e.inputSchema){let i=o;return await Promise.resolve(i(r,n))}else{let i=o;return await Promise.resolve(i(n))}}async handleAutomaticTaskPolling(e,r,n){if(!n.taskStore)throw new Error("No task store provided for task-capable tool.");let o=await this.validateToolInput(e,r.params.arguments,r.params.name),s=e.handler,i={...n,taskStore:n.taskStore},a=o?await Promise.resolve(s.createTask(o,i)):await Promise.resolve(s.createTask(i)),c=a.task.taskId,u=a.task,l=u.pollInterval??5e3;for(;u.status!=="completed"&&u.status!=="failed"&&u.status!=="cancelled";){await new Promise(m=>setTimeout(m,l));let d=await n.taskStore.getTask(c);if(!d)throw new O(A.InternalError,`Task ${c} not found during polling`);u=d}return await n.taskStore.getTaskResult(c)}setCompletionRequestHandler(){this._completionHandlerInitialized||(this.server.assertCanSetRequestHandler(ar(Cs)),this.server.registerCapabilities({completions:{}}),this.server.setRequestHandler(Cs,async e=>{switch(e.params.ref.type){case"ref/prompt":return nh(e),this.handlePromptCompletion(e,e.params.ref);case"ref/resource":return oh(e),this.handleResourceCompletion(e,e.params.ref);default:throw new O(A.InvalidParams,`Invalid completion reference: ${e.params.ref}`)}}),this._completionHandlerInitialized=!0)}async handlePromptCompletion(e,r){let n=this._registeredPrompts[r.name];if(!n)throw new O(A.InvalidParams,`Prompt ${r.name} not found`);if(!n.enabled)throw new O(A.InvalidParams,`Prompt ${r.name} disabled`);if(!n.argsSchema)return Lo;let s=Wt(n.argsSchema)?.[e.params.argument.name];if(!Rp(s))return Lo;let i=Fv(s);if(!i)return Lo;let a=await i(e.params.argument.value,e.params.context);return Gv(a)}async handleResourceCompletion(e,r){let n=Object.values(this._registeredResourceTemplates).find(i=>i.resourceTemplate.uriTemplate.toString()===r.uri);if(!n){if(this._registeredResources[r.uri])return Lo;throw new O(A.InvalidParams,`Resource template ${e.params.ref.uri} not found`)}let o=n.resourceTemplate.completeCallback(e.params.argument.name);if(!o)return Lo;let s=await o(e.params.argument.value,e.params.context);return Gv(s)}setResourceRequestHandlers(){this._resourceHandlersInitialized||(this.server.assertCanSetRequestHandler(ar(Ts)),this.server.assertCanSetRequestHandler(ar(Ps)),this.server.assertCanSetRequestHandler(ar(Es)),this.server.registerCapabilities({resources:{listChanged:!0}}),this.server.setRequestHandler(Ts,async(e,r)=>{let n=Object.entries(this._registeredResources).filter(([s,i])=>i.enabled).map(([s,i])=>({uri:s,name:i.name,...i.metadata})),o=[];for(let s of Object.values(this._registeredResourceTemplates)){if(!s.resourceTemplate.listCallback)continue;let i=await s.resourceTemplate.listCallback(r);for(let a of i.resources)o.push({...s.metadata,...a})}return{resources:[...n,...o]}}),this.server.setRequestHandler(Ps,async()=>({resourceTemplates:Object.entries(this._registeredResourceTemplates).map(([r,n])=>({name:r,uriTemplate:n.resourceTemplate.uriTemplate.toString(),...n.metadata}))})),this.server.setRequestHandler(Es,async(e,r)=>{let n=new URL(e.params.uri),o=this._registeredResources[n.toString()];if(o){if(!o.enabled)throw new O(A.InvalidParams,`Resource ${n} disabled`);return o.readCallback(n,r)}for(let s of Object.values(this._registeredResourceTemplates)){let i=s.resourceTemplate.uriTemplate.match(n.toString());if(i)return s.readCallback(n,i,r)}throw new O(A.InvalidParams,`Resource ${n} not found`)}),this._resourceHandlersInitialized=!0)}setPromptRequestHandlers(){this._promptHandlersInitialized||(this.server.assertCanSetRequestHandler(ar(Is)),this.server.assertCanSetRequestHandler(ar(Rs)),this.server.registerCapabilities({prompts:{listChanged:!0}}),this.server.setRequestHandler(Is,()=>({prompts:Object.entries(this._registeredPrompts).filter(([,e])=>e.enabled).map(([e,r])=>({name:e,title:r.title,description:r.description,arguments:r.argsSchema?jR(r.argsSchema):void 0}))})),this.server.setRequestHandler(Rs,async(e,r)=>{let n=this._registeredPrompts[e.params.name];if(!n)throw new O(A.InvalidParams,`Prompt ${e.params.name} not found`);if(!n.enabled)throw new O(A.InvalidParams,`Prompt ${e.params.name} disabled`);if(n.argsSchema){let o=dn(n.argsSchema),s=await Js(o,e.params.arguments);if(!s.success){let c="error"in s?s.error:"Unknown error",u=Gs(c);throw new O(A.InvalidParams,`Invalid arguments for prompt ${e.params.name}: ${u}`)}let i=s.data,a=n.callback;return await Promise.resolve(a(i,r))}else{let o=n.callback;return await Promise.resolve(o(r))}}),this._promptHandlersInitialized=!0)}resource(e,r,...n){let o;typeof n[0]=="object"&&(o=n.shift());let s=n[0];if(typeof r=="string"){if(this._registeredResources[r])throw new Error(`Resource ${r} is already registered`);let i=this._createRegisteredResource(e,void 0,r,o,s);return this.setResourceRequestHandlers(),this.sendResourceListChanged(),i}else{if(this._registeredResourceTemplates[e])throw new Error(`Resource template ${e} is already registered`);let i=this._createRegisteredResourceTemplate(e,void 0,r,o,s);return this.setResourceRequestHandlers(),this.sendResourceListChanged(),i}}registerResource(e,r,n,o){if(typeof r=="string"){if(this._registeredResources[r])throw new Error(`Resource ${r} is already registered`);let s=this._createRegisteredResource(e,n.title,r,n,o);return this.setResourceRequestHandlers(),this.sendResourceListChanged(),s}else{if(this._registeredResourceTemplates[e])throw new Error(`Resource template ${e} is already registered`);let s=this._createRegisteredResourceTemplate(e,n.title,r,n,o);return this.setResourceRequestHandlers(),this.sendResourceListChanged(),s}}_createRegisteredResource(e,r,n,o,s){let i={name:e,title:r,metadata:o,readCallback:s,enabled:!0,disable:()=>i.update({enabled:!1}),enable:()=>i.update({enabled:!0}),remove:()=>i.update({uri:null}),update:a=>{typeof a.uri<"u"&&a.uri!==n&&(delete this._registeredResources[n],a.uri&&(this._registeredResources[a.uri]=i)),typeof a.name<"u"&&(i.name=a.name),typeof a.title<"u"&&(i.title=a.title),typeof a.metadata<"u"&&(i.metadata=a.metadata),typeof a.callback<"u"&&(i.readCallback=a.callback),typeof a.enabled<"u"&&(i.enabled=a.enabled),this.sendResourceListChanged()}};return this._registeredResources[n]=i,i}_createRegisteredResourceTemplate(e,r,n,o,s){let i={resourceTemplate:n,title:r,metadata:o,readCallback:s,enabled:!0,disable:()=>i.update({enabled:!1}),enable:()=>i.update({enabled:!0}),remove:()=>i.update({name:null}),update:u=>{typeof u.name<"u"&&u.name!==e&&(delete this._registeredResourceTemplates[e],u.name&&(this._registeredResourceTemplates[u.name]=i)),typeof u.title<"u"&&(i.title=u.title),typeof u.template<"u"&&(i.resourceTemplate=u.template),typeof u.metadata<"u"&&(i.metadata=u.metadata),typeof u.callback<"u"&&(i.readCallback=u.callback),typeof u.enabled<"u"&&(i.enabled=u.enabled),this.sendResourceListChanged()}};this._registeredResourceTemplates[e]=i;let a=n.uriTemplate.variableNames;return Array.isArray(a)&&a.some(u=>!!n.completeCallback(u))&&this.setCompletionRequestHandler(),i}_createRegisteredPrompt(e,r,n,o,s){let i={title:r,description:n,argsSchema:o===void 0?void 0:Ir(o),callback:s,enabled:!0,disable:()=>i.update({enabled:!1}),enable:()=>i.update({enabled:!0}),remove:()=>i.update({name:null}),update:a=>{typeof a.name<"u"&&a.name!==e&&(delete this._registeredPrompts[e],a.name&&(this._registeredPrompts[a.name]=i)),typeof a.title<"u"&&(i.title=a.title),typeof a.description<"u"&&(i.description=a.description),typeof a.argsSchema<"u"&&(i.argsSchema=Ir(a.argsSchema)),typeof a.callback<"u"&&(i.callback=a.callback),typeof a.enabled<"u"&&(i.enabled=a.enabled),this.sendPromptListChanged()}};return this._registeredPrompts[e]=i,o&&Object.values(o).some(c=>{let u=c instanceof Ue?c._def?.innerType:c;return Rp(u)})&&this.setCompletionRequestHandler(),i}_createRegisteredTool(e,r,n,o,s,i,a,c,u){Op(e);let l={title:r,description:n,inputSchema:Jv(o),outputSchema:Jv(s),annotations:i,execution:a,_meta:c,handler:u,enabled:!0,disable:()=>l.update({enabled:!1}),enable:()=>l.update({enabled:!0}),remove:()=>l.update({name:null}),update:d=>{typeof d.name<"u"&&d.name!==e&&(typeof d.name=="string"&&Op(d.name),delete this._registeredTools[e],d.name&&(this._registeredTools[d.name]=l)),typeof d.title<"u"&&(l.title=d.title),typeof d.description<"u"&&(l.description=d.description),typeof d.paramsSchema<"u"&&(l.inputSchema=Ir(d.paramsSchema)),typeof d.outputSchema<"u"&&(l.outputSchema=Ir(d.outputSchema)),typeof d.callback<"u"&&(l.handler=d.callback),typeof d.annotations<"u"&&(l.annotations=d.annotations),typeof d._meta<"u"&&(l._meta=d._meta),typeof d.enabled<"u"&&(l.enabled=d.enabled),this.sendToolListChanged()}};return this._registeredTools[e]=l,this.setToolRequestHandlers(),this.sendToolListChanged(),l}tool(e,...r){if(this._registeredTools[e])throw new Error(`Tool ${e} is already registered`);let n,o,s,i;if(typeof r[0]=="string"&&(n=r.shift()),r.length>1){let c=r[0];if(Cp(c))o=r.shift(),r.length>1&&typeof r[0]=="object"&&r[0]!==null&&!Cp(r[0])&&(i=r.shift());else if(typeof c=="object"&&c!==null){if(Object.values(c).some(u=>typeof u=="object"&&u!==null))throw new Error(`Tool ${e} expected a Zod schema or ToolAnnotations, but received an unrecognized object`);i=r.shift()}}let a=r[0];return this._createRegisteredTool(e,void 0,n,o,s,i,{taskSupport:"forbidden"},void 0,a)}registerTool(e,r,n){if(this._registeredTools[e])throw new Error(`Tool ${e} is already registered`);let{title:o,description:s,inputSchema:i,outputSchema:a,annotations:c,_meta:u}=r;return this._createRegisteredTool(e,o,s,i,a,c,{taskSupport:"forbidden"},u,n)}prompt(e,...r){if(this._registeredPrompts[e])throw new Error(`Prompt ${e} is already registered`);let n;typeof r[0]=="string"&&(n=r.shift());let o;r.length>1&&(o=r.shift());let s=r[0],i=this._createRegisteredPrompt(e,void 0,n,o,s);return this.setPromptRequestHandlers(),this.sendPromptListChanged(),i}registerPrompt(e,r,n){if(this._registeredPrompts[e])throw new Error(`Prompt ${e} is already registered`);let{title:o,description:s,argsSchema:i}=r,a=this._createRegisteredPrompt(e,o,s,i,n);return this.setPromptRequestHandlers(),this.sendPromptListChanged(),a}isConnected(){return this.server.transport!==void 0}async sendLoggingMessage(e,r){return this.server.sendLoggingMessage(e,r)}sendResourceListChanged(){this.isConnected()&&this.server.sendResourceListChanged()}sendToolListChanged(){this.isConnected()&&this.server.sendToolListChanged()}sendPromptListChanged(){this.isConnected()&&this.server.sendPromptListChanged()}},Np=class{constructor(e,r){this._callbacks=r,this._uriTemplate=typeof e=="string"?new Bi(e):e}get uriTemplate(){return this._uriTemplate}get listCallback(){return this._callbacks.list}completeCallback(e){return this._callbacks.complete?.[e]}},ZR={type:"object",properties:{}};Lo={completion:{values:[],hasMore:!1}}});import ih from"node:process";Qr();var As=class{append(e){this._buffer=this._buffer?Buffer.concat([this._buffer,e]):e}readMessage(){if(!this._buffer)return null;let e=this._buffer.indexOf(`
|
|
40
40
|
`);if(e===-1)return null;let r=this._buffer.toString("utf8",0,e).replace(/\r$/,"");return this._buffer=this._buffer.subarray(e+1),s0(r)}clear(){this._buffer=void 0}};function s0(t){return Km.parse(JSON.parse(t))}function sh(t){return JSON.stringify(t)+`
|
|
41
41
|
`}var eo=class{constructor(e=ih.stdin,r=ih.stdout){this._stdin=e,this._stdout=r,this._readBuffer=new As,this._started=!1,this._ondata=n=>{this._readBuffer.append(n),this.processReadBuffer()},this._onerror=n=>{this.onerror?.(n)}}async start(){if(this._started)throw new Error("StdioServerTransport already started! If using Server class, note that connect() calls start() automatically.");this._started=!0,this._stdin.on("data",this._ondata),this._stdin.on("error",this._onerror)}processReadBuffer(){for(;;)try{let e=this._readBuffer.readMessage();if(e===null)break;this.onmessage?.(e)}catch(e){this.onerror?.(e)}}async close(){this._stdin.off("data",this._ondata),this._stdin.off("error",this._onerror),this._stdin.listenerCount("data")===0&&this._stdin.pause(),this._readBuffer.clear(),this.onclose?.()}send(e){return new Promise(r=>{let n=sh(e);this._stdout.write(n)?r():this._stdout.once("drain",r)})}};import{attachOursClient as _b,OursError as uO,resolveDaemonConfig as lO}from"@ours.network/sdk";import{randomUUID as i0}from"node:crypto";import{chmod as a0,mkdir as c0,readFile as u0,rename as l0,unlink as d0,writeFile as p0}from"node:fs/promises";import{homedir as f0}from"node:os";import{dirname as m0,resolve as to}from"node:path";var ah=1,h0="OURS_MCP_CONFIG",lh=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/,g0=()=>({version:1,daemons:{},instances:{}});function Zu(t=process.env){let e=(t[h0]??"").trim();return to(e||to(f0(),".ours-mcp","config.json"))}function ch(t,e,r,n){if(!t||typeof t!="object"||Array.isArray(t))throw new Error(`Invalid ours-mcp application identity config at ${e}: "${r}s" must be an object.`);let o={};for(let[s,i]of Object.entries(t)){if(!i||typeof i!="object"||Array.isArray(i))throw new Error(`Invalid ours-mcp application identity config at ${e}: ${r} ${JSON.stringify(s)} must be an object.`);let a=i;if(!Array.isArray(a.identities)||a.identities.some(c=>typeof c!="string"||c.length===0))throw new Error(`Invalid ours-mcp application identity config at ${e}: ${r} ${JSON.stringify(s)} has an invalid identity list.`);o[n(s)]={identities:[...new Set(a.identities)].sort()}}return o}function y0(t,e){let r;try{r=JSON.parse(t)}catch(i){throw new Error(`Invalid ours-mcp application identity config at ${e}: ${String(i)}`)}if(!r||typeof r!="object"||Array.isArray(r))throw new Error(`Invalid ours-mcp application identity config at ${e}: expected an object.`);let n=r;if(n.version!==ah)throw new Error(`Unsupported ours-mcp application identity config version at ${e}: expected ${ah}, found ${String(n.version)}.`);let o=ch(n.daemons,e,"daemon",to),s=n.instances===void 0?{}:ch(n.instances,e,"instance",i=>{if(!lh.test(i))throw new Error(`Invalid ours-mcp application identity config at ${e}: instance ${JSON.stringify(i)} must be a lowercase UUID.`);return i});return{version:1,daemons:o,instances:s}}async function Au(t){try{return y0(await u0(t,"utf8"),t)}catch(e){if(e.code==="ENOENT")return g0();throw e}}async function uh(t,e){let r=m0(t);await c0(r,{recursive:!0,mode:448});let n=`${t}.${process.pid}.${i0()}.tmp`;try{await p0(n,`${JSON.stringify(e,null,2)}
|
|
42
|
-
`,{mode:384,flag:"wx"}),await l0(n,t),await a0(t,384)}catch(o){try{await d0(n)}catch{}throw o}}var en=class{stateDir;instanceId;path;constructor(e,r={}){if(typeof e=="string")this.stateDir=to(e),this.instanceId=null;else{if(!e||!lh.test(e.instanceId))throw new Error("Application identity instanceId must be a lowercase UUID.");this.stateDir=null,this.instanceId=e.instanceId}this.path=to(r.path??Zu(r.env))}rows(e){return this.instanceId===null?e.daemons:e.instances}key(){return this.instanceId??this.stateDir}async list(){let e=await Au(this.path);return[...this.rows(e)[this.key()]?.identities??[]]}async has(e){return(await this.list()).includes(e)}async add(e){if(!e)throw new Error("Cannot add an empty identity name to ours-mcp.");let r=await Au(this.path),n=this.rows(r),o=this.key(),s=n[o]?.identities??[];s.includes(e)||(n[o]={identities:[...s,e].sort()},await uh(this.path,r))}async remove(e){let r=await Au(this.path),n=this.rows(r),o=this.key(),s=n[o];if(!s?.identities.includes(e))return;let i=s.identities.filter(a=>a!==e);i.length===0?delete n[o]:n[o]={identities:i},await uh(this.path,r)}};async function dh(t,e){let r=new Set(await t.list());return e.filter(n=>r.has(n.name))}import{existsSync as _0,lstatSync as fh,readFileSync as v0}from"node:fs";import{homedir as ph}from"node:os";import{resolve as Zs}from"node:path";var ju=["endpoint","expectedInstanceId","credentialPath"],b0=["port","stateDir","apiToken","apiVisibility"],x0=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/,w0=["OURS_API_TOKEN","OURS_PORT","OURS_STATE_DIR","OURS_DAEMON_ID"];function je(t){return new Error(`Invalid external host profile: ${t}`)}function ro(t){if(!t||typeof t!="object"||Array.isArray(t))throw je("expected a complete host profile object.");let e=t;if(ju.filter(c=>Object.hasOwn(e,c)).length!==ju.length)throw je("expected a complete host profile tuple: endpoint, expectedInstanceId, credentialPath.");let n=b0.filter(c=>Object.hasOwn(e,c));if(n.length)throw je(`legacy selection keys cannot be mixed with a host profile (${n.join(", ")}).`);let o=e.endpoint,s=e.expectedInstanceId,i=e.credentialPath;if(typeof o!="string"||o.trim()!==o||o==="")throw je("endpoint must be a non-empty HTTP origin.");if(typeof s!="string"||!x0.test(s))throw je("expectedInstanceId must be a lowercase UUID.");if(typeof i!="string"||i===""||!i.startsWith("/")||Zs(i)!==i)throw je("credentialPath must be a normalized absolute path.");let a;try{a=new URL(o)}catch{throw je("endpoint must be an HTTP origin.")}if(a.protocol!=="http:"||a.username||a.password||a.pathname!=="/"||a.search||a.hash)throw je("endpoint must be an HTTP origin without credentials, path, query, or fragment.");return{endpoint:a.origin,expectedInstanceId:s,credentialPath:i}}function $0(t){let e;try{e=v0(t,"utf8")}catch{throw new Error(`Cannot read host profile ${JSON.stringify(t)}.`)}let r;try{r=JSON.parse(e)}catch{throw je(`config ${JSON.stringify(t)} is not valid JSON.`)}if(!r||typeof r!="object"||Array.isArray(r))throw je(`config ${JSON.stringify(t)} must be an object.`);return r}function k0(t){let e;try{e=fh(t)}catch{throw new Error(`Cannot read host profile ${JSON.stringify(t)}.`)}if(!e.isFile())throw je(`config ${JSON.stringify(t)} must be a regular file.`);let r=process.getuid?.();if(r===void 0||e.uid!==r)throw je(`config ${JSON.stringify(t)} must be owned by the current user.`);if(e.mode&63)throw je(`config ${JSON.stringify(t)} must have private permissions.`)}function S0(t){let e=$0(t);return ju.filter(n=>Object.hasOwn(e,n)).length===0?null:(k0(t),ro(e))}function z0(t,e){return(t[e]??"").trim()!==""}function T0(t=process.env){let e=(t.OURS_CONFIG??"").trim(),r=Zs(t.HOME||ph(),".ours-client","profile.json"),n=e;if(!n)try{fh(r),n=r}catch(i){if(i.code!=="ENOENT")throw new Error(`Cannot read host profile ${JSON.stringify(r)}.`);if(n=Zs(ph(),".ours","config.json"),!_0(n))return null}let o=S0(n);if(o===null){if(Zs(n)===r)throw je("managed client config must contain a complete host profile tuple.");return null}let s=w0.filter(i=>z0(t,i));if(s.length)throw je(`${s.join(", ")} conflicts with host-profile mode.`);return{profile:o,configPath:n}}function Mu(t=process.env){return T0(t)?.profile??null}import{createHash as Z0,randomUUID as bh}from"node:crypto";import{chmod as _h,mkdir as j0,readFile as M0,rename as D0,unlink as q0,writeFile as L0}from"node:fs/promises";import{dirname as xh,join as F0,resolve as U0}from"node:path";import{attachOursClient as V0}from"@ours.network/sdk";import{createHash as P0}from"node:crypto";import{openSync as E0,closeSync as I0,lstatSync as Du,mkdirSync as R0,chmodSync as O0,constants as js}from"node:fs";import{join as mh}from"node:path";import{createRequire as hh}from"node:module";var N0=5e3,tn=null,gh=!1;function C0(){if(tn)return tn;if(gh)throw new Error("No SQLite implementation available for native session guard");gh=!0;try{return tn=hh(import.meta.url)("node:sqlite").DatabaseSync,tn}catch{try{let t=hh(import.meta.url)("better-sqlite3");return tn=t.default??t,tn}catch{throw new Error("Native session guard requires node:sqlite (Node >=22.13) or better-sqlite3")}}}function A0(t){try{let r=E0(t,js.O_RDWR|js.O_CREAT|js.O_EXCL|js.O_NOFOLLOW,384);I0(r)}catch(r){if(r.code!=="EEXIST")throw r}let e=Du(t);if(!e.isFile()||e.uid!==process.getuid()||e.mode&63||e.nlink!==1)throw new Error("Native session guard file must be an owner-only regular file")}function yh(t){let e=process.getuid(),r=mh(`/tmp/ours-${e}`,"session-guards");R0(r,{recursive:!0,mode:448});try{O0(r,448)}catch{}let n=P0("sha256").update(t).digest("hex"),o=mh(r,`${n}.guard`);A0(o);let s=Du(o),i=C0(),a=new i(o);try{let c=Du(o);if(s.dev!==c.dev||s.ino!==c.ino||s.mode!==c.mode||s.uid!==c.uid)throw new Error("Native session guard file changed during acquisition");return a.exec(`PRAGMA busy_timeout=${N0}; BEGIN EXCLUSIVE`),()=>{try{a.close()}catch{}}}catch(c){try{a.close()}catch{}throw c}}var Lu=1,wh=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/,Vt=new Map,Ms=new Map;function H0(t){if(typeof t!="string"||t.length===0||t.length>4096||t.trim()!==t||t.includes("\0"))throw new Error("Native session metadata is missing or invalid for this host-profile tool call.");return t}function B0(t,e,r){if(!t||!t.startsWith("/")||U0(t)!==t)throw new Error("Native session host record root must be a normalized absolute path.");if(!wh.test(e))throw new Error("Native session daemon instance must be a lowercase UUID.");let n=Z0("sha256").update(H0(r),"utf8").digest("hex");return F0(t,"sessions",e,`${n}.json`)}function J0(t,e){let r;try{r=JSON.parse(t)}catch(s){throw new Error(`Invalid native session record at ${e}: ${String(s)}`)}if(!r||typeof r!="object"||Array.isArray(r))throw new Error(`Invalid native session record at ${e}: expected an object.`);let n=r;if(Object.keys(n).sort().join(",")!=="ownerInstanceId,state,version"||n.version!==Lu||typeof n.ownerInstanceId!="string"||!wh.test(n.ownerInstanceId)||!["active","pending","ended"].includes(String(n.state)))throw new Error(`Invalid native session record at ${e}.`);return n}async function qu(t){try{return J0(await M0(t,"utf8"),t)}catch(e){if(e.code==="ENOENT")return null;throw e}}async function $h(t,e){let r=xh(t);await j0(r,{recursive:!0,mode:448}),await _h(r,448);let n=`${t}.${process.pid}.${bh()}.tmp`;try{await L0(n,`${JSON.stringify(e,null,2)}
|
|
42
|
+
`,{mode:384,flag:"wx"}),await l0(n,t),await a0(t,384)}catch(o){try{await d0(n)}catch{}throw o}}var en=class{stateDir;instanceId;path;constructor(e,r={}){if(typeof e=="string")this.stateDir=to(e),this.instanceId=null;else{if(!e||!lh.test(e.instanceId))throw new Error("Application identity instanceId must be a lowercase UUID.");this.stateDir=null,this.instanceId=e.instanceId}this.path=to(r.path??Zu(r.env))}rows(e){return this.instanceId===null?e.daemons:e.instances}key(){return this.instanceId??this.stateDir}async list(){let e=await Au(this.path);return[...this.rows(e)[this.key()]?.identities??[]]}async has(e){return(await this.list()).includes(e)}async add(e){if(!e)throw new Error("Cannot add an empty identity name to ours-mcp.");let r=await Au(this.path),n=this.rows(r),o=this.key(),s=n[o]?.identities??[];s.includes(e)||(n[o]={identities:[...s,e].sort()},await uh(this.path,r))}async remove(e){let r=await Au(this.path),n=this.rows(r),o=this.key(),s=n[o];if(!s?.identities.includes(e))return;let i=s.identities.filter(a=>a!==e);i.length===0?delete n[o]:n[o]={identities:i},await uh(this.path,r)}};async function dh(t,e){let r=new Set(await t.list());return e.filter(n=>r.has(n.name))}import{existsSync as _0,lstatSync as fh,readFileSync as v0}from"node:fs";import{homedir as ph}from"node:os";import{resolve as Zs}from"node:path";var ju=["endpoint","expectedInstanceId","credentialPath"],b0=["port","stateDir","apiToken","apiVisibility"],x0=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/,w0=["OURS_API_TOKEN","OURS_PORT","OURS_STATE_DIR","OURS_DAEMON_ID"];function je(t){return new Error(`Invalid external host profile: ${t}`)}function ro(t){if(!t||typeof t!="object"||Array.isArray(t))throw je("expected a complete host profile object.");let e=t;if(ju.filter(c=>Object.hasOwn(e,c)).length!==ju.length)throw je("expected a complete host profile tuple: endpoint, expectedInstanceId, credentialPath.");let n=b0.filter(c=>Object.hasOwn(e,c));if(n.length)throw je(`legacy selection keys cannot be mixed with a host profile (${n.join(", ")}).`);let o=e.endpoint,s=e.expectedInstanceId,i=e.credentialPath;if(typeof o!="string"||o.trim()!==o||o==="")throw je("endpoint must be a non-empty HTTP or HTTPS origin.");if(typeof s!="string"||!x0.test(s))throw je("expectedInstanceId must be a lowercase UUID.");if(typeof i!="string"||i===""||!i.startsWith("/")||Zs(i)!==i)throw je("credentialPath must be a normalized absolute path.");let a;try{a=new URL(o)}catch{throw je("endpoint must be an HTTP or HTTPS origin.")}if(a.protocol!=="http:"&&a.protocol!=="https:"||a.username||a.password||a.pathname!=="/"||a.search||a.hash)throw je("endpoint must be an HTTP or HTTPS origin without credentials, path, query, or fragment.");return{endpoint:a.origin,expectedInstanceId:s,credentialPath:i}}function $0(t){let e;try{e=v0(t,"utf8")}catch{throw new Error(`Cannot read host profile ${JSON.stringify(t)}.`)}let r;try{r=JSON.parse(e)}catch{throw je(`config ${JSON.stringify(t)} is not valid JSON.`)}if(!r||typeof r!="object"||Array.isArray(r))throw je(`config ${JSON.stringify(t)} must be an object.`);return r}function k0(t){let e;try{e=fh(t)}catch{throw new Error(`Cannot read host profile ${JSON.stringify(t)}.`)}if(!e.isFile())throw je(`config ${JSON.stringify(t)} must be a regular file.`);let r=process.getuid?.();if(r===void 0||e.uid!==r)throw je(`config ${JSON.stringify(t)} must be owned by the current user.`);if(e.mode&63)throw je(`config ${JSON.stringify(t)} must have private permissions.`)}function S0(t){let e=$0(t);return ju.filter(n=>Object.hasOwn(e,n)).length===0?null:(k0(t),ro(e))}function z0(t,e){return(t[e]??"").trim()!==""}function T0(t=process.env){let e=(t.OURS_CONFIG??"").trim(),r=Zs(t.HOME||ph(),".ours-client","profile.json"),n=e;if(!n)try{fh(r),n=r}catch(i){if(i.code!=="ENOENT")throw new Error(`Cannot read host profile ${JSON.stringify(r)}.`);if(n=Zs(ph(),".ours","config.json"),!_0(n))return null}let o=S0(n);if(o===null){if(Zs(n)===r)throw je("managed client config must contain a complete host profile tuple.");return null}let s=w0.filter(i=>z0(t,i));if(s.length)throw je(`${s.join(", ")} conflicts with host-profile mode.`);return{profile:o,configPath:n}}function Mu(t=process.env){return T0(t)?.profile??null}import{createHash as Z0,randomUUID as bh}from"node:crypto";import{chmod as _h,mkdir as j0,readFile as M0,rename as D0,unlink as q0,writeFile as L0}from"node:fs/promises";import{dirname as xh,join as F0,resolve as U0}from"node:path";import{attachOursClient as V0}from"@ours.network/sdk";import{createHash as P0}from"node:crypto";import{openSync as E0,closeSync as I0,lstatSync as Du,mkdirSync as R0,chmodSync as O0,constants as js}from"node:fs";import{join as mh}from"node:path";import{createRequire as hh}from"node:module";var N0=5e3,tn=null,gh=!1;function C0(){if(tn)return tn;if(gh)throw new Error("No SQLite implementation available for native session guard");gh=!0;try{return tn=hh(import.meta.url)("node:sqlite").DatabaseSync,tn}catch{try{let t=hh(import.meta.url)("better-sqlite3");return tn=t.default??t,tn}catch{throw new Error("Native session guard requires node:sqlite (Node >=22.13) or better-sqlite3")}}}function A0(t){try{let r=E0(t,js.O_RDWR|js.O_CREAT|js.O_EXCL|js.O_NOFOLLOW,384);I0(r)}catch(r){if(r.code!=="EEXIST")throw r}let e=Du(t);if(!e.isFile()||e.uid!==process.getuid()||e.mode&63||e.nlink!==1)throw new Error("Native session guard file must be an owner-only regular file")}function yh(t){let e=process.getuid(),r=mh(`/tmp/ours-${e}`,"session-guards");R0(r,{recursive:!0,mode:448});try{O0(r,448)}catch{}let n=P0("sha256").update(t).digest("hex"),o=mh(r,`${n}.guard`);A0(o);let s=Du(o),i=C0(),a=new i(o);try{let c=Du(o);if(s.dev!==c.dev||s.ino!==c.ino||s.mode!==c.mode||s.uid!==c.uid)throw new Error("Native session guard file changed during acquisition");return a.exec(`PRAGMA busy_timeout=${N0}; BEGIN EXCLUSIVE`),()=>{try{a.close()}catch{}}}catch(c){try{a.close()}catch{}throw c}}var Lu=1,wh=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/,Vt=new Map,Ms=new Map;function H0(t){if(typeof t!="string"||t.length===0||t.length>4096||t.trim()!==t||t.includes("\0"))throw new Error("Native session metadata is missing or invalid for this host-profile tool call.");return t}function B0(t,e,r){if(!t||!t.startsWith("/")||U0(t)!==t)throw new Error("Native session host record root must be a normalized absolute path.");if(!wh.test(e))throw new Error("Native session daemon instance must be a lowercase UUID.");let n=Z0("sha256").update(H0(r),"utf8").digest("hex");return F0(t,"sessions",e,`${n}.json`)}function J0(t,e){let r;try{r=JSON.parse(t)}catch(s){throw new Error(`Invalid native session record at ${e}: ${String(s)}`)}if(!r||typeof r!="object"||Array.isArray(r))throw new Error(`Invalid native session record at ${e}: expected an object.`);let n=r;if(Object.keys(n).sort().join(",")!=="ownerInstanceId,state,version"||n.version!==Lu||typeof n.ownerInstanceId!="string"||!wh.test(n.ownerInstanceId)||!["active","pending","ended"].includes(String(n.state)))throw new Error(`Invalid native session record at ${e}.`);return n}async function qu(t){try{return J0(await M0(t,"utf8"),t)}catch(e){if(e.code==="ENOENT")return null;throw e}}async function $h(t,e){let r=xh(t);await j0(r,{recursive:!0,mode:448}),await _h(r,448);let n=`${t}.${process.pid}.${bh()}.tmp`;try{await L0(n,`${JSON.stringify(e,null,2)}
|
|
43
43
|
`,{mode:384,flag:"wx"}),await D0(n,t),await _h(t,384)}catch(o){try{await q0(n)}catch{}throw o}}async function G0(t,e){let r=Ms.get(t)??Promise.resolve(),n,o=new Promise(a=>{n=a}),s=r.catch(()=>{}).then(()=>o);Ms.set(t,s),await r.catch(()=>{});let i;try{return i=yh(t),await e()}finally{try{i?.()}finally{n(),Ms.get(t)===s&&Ms.delete(t)}}}function kh(t,e){return V0({endpoint:t.endpoint,expectedInstanceId:t.expectedInstanceId,credentialPath:t.credentialPath,sessionMode:"external",leaseToken:e,env:{}})}function vh(t,e,r){let n=Vt.get(t);if(n?.ownerInstanceId===r)return n.promise;n&&(Vt.delete(t),n.promise.then(i=>i.close()).catch(()=>{}));let o=kh(e,r),s={ownerInstanceId:r,promise:o};return Vt.set(t,s),o.catch(()=>{Vt.get(t)===s&&Vt.delete(t)}),o}async function K0(t,e,r){let n=Vt.get(t),o=n?.ownerInstanceId===r?await n.promise:await kh(e,r);try{await o.releaseLease()}finally{n?.ownerInstanceId!==r&&await o.close()}}async function W0(t,e,r){await K0(t,e,r);let n=await qu(t);n?.state==="pending"&&n.ownerInstanceId===r&&await $h(t,{version:Lu,ownerInstanceId:r,state:"ended"});let o=Vt.get(t);o?.ownerInstanceId===r&&(Vt.delete(t),o.promise.then(s=>s.close()).catch(()=>{}))}async function Sh(t,e,r=process.env){return Y0(t,e,xh(Zu(r)))}async function Y0(t,e,r){let n=ro(t),o=B0(r,n.expectedInstanceId,e);return G0(o,async()=>{let s=await qu(o);if(s?.state==="pending"&&(await W0(o,n,s.ownerInstanceId),s=await qu(o)),s?.state==="active")return vh(o,n,s.ownerInstanceId);let i=bh();return await $h(o,{version:Lu,ownerInstanceId:i,state:"active"}),vh(o,n,i)})}Ap();qt();import{OursError as Zp}from"@ours.network/sdk";function L(t,e=!1){return{content:[{type:"text",text:t}],isError:e}}var jp=new WeakMap;function Gi(t,e){jp.set(t,e)}function Uo(t){return jp.get(t)??null}function MR(t){jp.delete(t)}async function DR(t){let e=Uo(t);if(!e)return!1;try{return await t.chooseIdentity({name:e,force:!1}),!0}catch{return MR(t),!1}}async function K(t,e,r){let n=await t,o;try{o=await e(n)}catch(s){if(s instanceof Zp&&s.code==="NOT_BOUND"&&await DR(n))try{return r(await e(n))}catch(i){if(i instanceof Zp)return L(i.message,!0);throw i}if(s instanceof Zp)return L(s.message,!0);throw s}return Uo(n)===null&&n.currentIdentity().then(s=>{Gi(n,s.name)}).catch(()=>{}),r(o)}var Mp=S.lazy(()=>S.union([S.null(),S.boolean(),S.number(),S.string(),S.array(Mp),S.record(Mp)]));function Xv(t,e){t.tool("list_contact_commands","List the typed commands a contact currently advertises. The returned catalog is data; remote commands are not registered as MCP tools.",{contact:S.string().min(1).describe("Contact name or container id.")},async({contact:r},n)=>K(e(n),o=>o.listContactCommands({contact:r}),o=>{let s={contact:r,count:o.length,commands:o};return{content:[{type:"text",text:JSON.stringify(s,null,2)}],structuredContent:s,isError:!1}})),t.tool("send_command","Send a typed command to a contact after the SDK validates it against that contact's advertised schema. Use get_messages to retrieve a correlated command_result whose reply_to.wire_id matches request_wire_id.",{contact:S.string().min(1).describe("Contact name or container id."),command:S.string().min(1).describe("Advertised command name."),arguments:Mp.describe("Any JSON-compatible command arguments accepted by the advertised schema.")},async({contact:r,command:n,arguments:o},s)=>K(e(s),i=>i.sendCommand({contact:r,command:n,arguments:o}),i=>{let a={request_wire_id:i.wireId,outcome:i};return{content:[{type:"text",text:JSON.stringify(a,null,2)}],structuredContent:a,isError:i.kind==="refused"}}))}qt();function qR(t){let e=new Map;for(let r of t)e.set(r.name,(e.get(r.name)??0)+1);return e}function Qv(t){let e=qR(t);return t.map(r=>`\u2022 ${r.name} \u2014 ${r.container_id}${r.rootTag??""}${r.degradedQueued!==void 0?` \u2014 \u26A0 keys pending restore (${r.degradedQueued} queued)`:""}${(e.get(r.name)??0)>1?" \u2014 \u26A0 DUPLICATE NAME: sends to this name abort; address by container id, repair with rename_contact":""}${r.renamedFrom!==void 0?` \u2014 \u26A0 renamed on import (two contacts were named "${r.renamedFrom}"; do NOT assume the one keeping the bare name is the live one \u2014 verify by container id, settle with rename_contact)`:""}`)}function LR(t){if(!t)return"";let e=t.root_name||t.root_cid;return t.role_id?` [role "${t.role_id}" of ${e}]`:` [root identity of ${e}]`}function eb(t,e){t.tool("generate_invite",'Generate an invite to share out-of-band with another agent. The invite carries your identity and display name. If you pass a name, whoever redeems the invite is registered under it; without a name, the redeemer is registered under the name they announce when accepting. mode selects the invite kind: "one_time" (the default when omitted \u2014 consumed by the first redemption) or "public" (reusable, meant for open posting; every redeemer gets an independent channel; close it with revoke_invite \u2014 it has no expiry and is never consumed). A public invite cannot pre-assign a contact name, and does not survive a daemon restart (it must be re-generated and re-posted). Requires a bound identity.',{name:S.string().min(1).optional().describe('Optional name to register the peer who redeems this invite, e.g. "Bob". Omit to register them under their own name on acceptance. Not allowed with mode "public".'),mode:S.enum(["one_time","public"]).optional().describe('Invite kind. Omitted means "one_time" (single redemption, unchanged legacy behavior). "public" mints a reusable invite for open posting.')},async({name:r,mode:n},o)=>K(e(o),s=>s.generateInvite({name:r,mode:n}),s=>{let i=s.mode==="public"?`Reusable public invite created (invite_id ${s.inviteId}). Anyone holding the blob can redeem it, each as an independent contact, until you revoke_invite it. It will NOT survive a daemon restart \u2014 re-generate and re-post after one.`:r?`One-time invite for "${r}" created (invite_id ${s.inviteId}).`:`One-time invite created (invite_id ${s.inviteId}) \u2014 the contact will be registered under the name the recipient announces when accepting.`;return L(`${i} Share this blob out-of-band (they paste it into add_contact):
|
|
44
44
|
|
|
45
45
|
${s.blob}`)})),t.tool("list_invites","List the outstanding invites the bound identity has minted and not yet seen redeemed or revoked: invite_id, kind (one_time | public), assigned peer name if any, and creation time. Carries no key material. Use revoke_invite to close one \u2014 essential for public invites, which are never consumed.",{},async(r,n)=>K(e(n),o=>o.listInvites(),o=>{if(o.length===0)return L("No outstanding invites.");let s=o.map(i=>`\u2022 ${i.invite_id} \u2014 ${i.mode}${i.assigned?`, assigned name "${i.assigned}"`:""}${i.created?`, created ${i.created}`:""}`);return L(`Outstanding invites (${o.length}):
|
package/dist/host-client.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{existsSync as it,lstatSync as U,readFileSync as st}from"node:fs";import{homedir as J}from"node:os";import{resolve as I}from"node:path";var O=["endpoint","expectedInstanceId","credentialPath"],at=["port","stateDir","apiToken","apiVisibility"],ct=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/,dt=["OURS_API_TOKEN","OURS_PORT","OURS_STATE_DIR","OURS_DAEMON_ID"];function l(t){return new Error(`Invalid external host profile: ${t}`)}function w(t){if(!t||typeof t!="object"||Array.isArray(t))throw l("expected a complete host profile object.");let r=t;if(O.filter(d=>Object.hasOwn(r,d)).length!==O.length)throw l("expected a complete host profile tuple: endpoint, expectedInstanceId, credentialPath.");let n=at.filter(d=>Object.hasOwn(r,d));if(n.length)throw l(`legacy selection keys cannot be mixed with a host profile (${n.join(", ")}).`);let o=r.endpoint,i=r.expectedInstanceId,
|
|
2
|
-
${JSON.stringify(It(u),null,2)}`}],isError:!1}}}catch(u){return{...e,result:{content:[{type:"text",text:`define_local_identity_file failed: ${u instanceof Error?u.message:String(u)}`}],isError:!0}}}}if(o?.name!=="save_file")return e;let i=e.result,
|
|
3
|
-
`,{mode:384,flag:"wx"}),await Tt(n,t),await K(t,384)}catch(o){try{await Ht(n)}catch{}throw o}}async function Z(t,r){let e=S.get(t)??Promise.resolve(),n,o=new Promise(
|
|
1
|
+
import{existsSync as it,lstatSync as U,readFileSync as st}from"node:fs";import{homedir as J}from"node:os";import{resolve as I}from"node:path";var O=["endpoint","expectedInstanceId","credentialPath"],at=["port","stateDir","apiToken","apiVisibility"],ct=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/,dt=["OURS_API_TOKEN","OURS_PORT","OURS_STATE_DIR","OURS_DAEMON_ID"];function l(t){return new Error(`Invalid external host profile: ${t}`)}function w(t){if(!t||typeof t!="object"||Array.isArray(t))throw l("expected a complete host profile object.");let r=t;if(O.filter(d=>Object.hasOwn(r,d)).length!==O.length)throw l("expected a complete host profile tuple: endpoint, expectedInstanceId, credentialPath.");let n=at.filter(d=>Object.hasOwn(r,d));if(n.length)throw l(`legacy selection keys cannot be mixed with a host profile (${n.join(", ")}).`);let o=r.endpoint,i=r.expectedInstanceId,a=r.credentialPath;if(typeof o!="string"||o.trim()!==o||o==="")throw l("endpoint must be a non-empty HTTP or HTTPS origin.");if(typeof i!="string"||!ct.test(i))throw l("expectedInstanceId must be a lowercase UUID.");if(typeof a!="string"||a===""||!a.startsWith("/")||I(a)!==a)throw l("credentialPath must be a normalized absolute path.");let s;try{s=new URL(o)}catch{throw l("endpoint must be an HTTP or HTTPS origin.")}if(s.protocol!=="http:"&&s.protocol!=="https:"||s.username||s.password||s.pathname!=="/"||s.search||s.hash)throw l("endpoint must be an HTTP or HTTPS origin without credentials, path, query, or fragment.");return{endpoint:s.origin,expectedInstanceId:i,credentialPath:a}}function lt(t){let r;try{r=st(t,"utf8")}catch{throw new Error(`Cannot read host profile ${JSON.stringify(t)}.`)}let e;try{e=JSON.parse(r)}catch{throw l(`config ${JSON.stringify(t)} is not valid JSON.`)}if(!e||typeof e!="object"||Array.isArray(e))throw l(`config ${JSON.stringify(t)} must be an object.`);return e}function ft(t){let r;try{r=U(t)}catch{throw new Error(`Cannot read host profile ${JSON.stringify(t)}.`)}if(!r.isFile())throw l(`config ${JSON.stringify(t)} must be a regular file.`);let e=process.getuid?.();if(e===void 0||r.uid!==e)throw l(`config ${JSON.stringify(t)} must be owned by the current user.`);if(r.mode&63)throw l(`config ${JSON.stringify(t)} must have private permissions.`)}function C(t){let r=lt(t);return O.filter(n=>Object.hasOwn(r,n)).length===0?null:(ft(t),w(r))}function ut(t,r){return(t[r]??"").trim()!==""}function A(t=process.env){let r=(t.OURS_CONFIG??"").trim(),e=I(t.HOME||J(),".ours-client","profile.json"),n=r;if(!n)try{U(e),n=e}catch(a){if(a.code!=="ENOENT")throw new Error(`Cannot read host profile ${JSON.stringify(e)}.`);if(n=I(J(),".ours","config.json"),!it(n))return null}let o=C(n);if(o===null){if(I(n)===e)throw l("managed client config must contain a complete host profile tuple.");return null}let i=dt.filter(a=>ut(t,a));if(i.length)throw l(`${i.join(", ")} conflicts with host-profile mode.`);return{profile:o,configPath:n}}function D(t=process.env){return A(t)?.profile??null}import{createReadStream as pt,createWriteStream as mt,mkdirSync as yt,statSync as L}from"node:fs";import{basename as wt,dirname as gt,isAbsolute as ht,resolve as q}from"node:path";import{isDeepStrictEqual as vt}from"node:util";import{buildIdentityFile as It,writeIdentityFile as Et}from"@ours.network/sdk/connector";import{Readable as G}from"node:stream";import{pipeline as j}from"node:stream/promises";function $(t){return t.reason instanceof Error?t.reason:new Error(String(t.reason??"operation cancelled"))}function g(t){if(t?.aborted)throw $(t)}function W(t){return t.method!=="tools/call"||!t.params||typeof t.params!="object"?null:t.params}async function St(t,r,e){g(e);let n=W(r);if(n?.name!=="send_file"||typeof n.arguments?.path!="string")return r;let o=n.arguments,i=o.path;if(o.upload_id!==void 0||o.data_base64!==void 0)throw new Error("send_file accepts exactly one host file input.");let a=q(i),s=L(a).size,d=typeof o.filename=="string"&&o.filename?o.filename:wt(a),R=typeof o.mime=="string"?o.mime:void 0,f=pt(a),p=()=>f.destroy($(e));e?.addEventListener("abort",p,{once:!0});let c;try{let u=G.toWeb(f);c=await t.uploadFile(u,{filename:d,mime:R,size:s}),g(e)}finally{e?.removeEventListener("abort",p),e?.aborted&&f.destroy()}let y={...o,upload_id:c.upload_id,filename:d};return delete y.path,{...r,params:{...r.params,arguments:y}}}async function bt(t,r,e,n){g(n);let o=W(r);if(o?.name==="define_local_identity_file"){let f=e.result;if(f?.isError===!0)return e;let p=o.arguments??{},c={name:p.name,path:p.path,force:p.force??!1,expose_local:p.expose_local??!0,local_auto_accept:p.local_auto_accept??!0,overwrite:p.overwrite??!1},y=f?.structuredContent;if(!vt(y?.oursHostIdentityFile,c)||typeof c.name!="string"||typeof c.path!="string"||!ht(c.path)||[c.force,c.expose_local,c.local_auto_accept,c.overwrite].some(u=>typeof u!="boolean"))throw new Error("define_local_identity_file returned an invalid or mismatched host intent.");try{let u={name:c.name,force:c.force,exposeLocal:c.expose_local,localAutoAccept:c.local_auto_accept},N=Et(c.path,u,c.overwrite);return{...e,result:{content:[{type:"text",text:`Wrote ${N}:
|
|
2
|
+
${JSON.stringify(It(u),null,2)}`}],isError:!1}}}catch(u){return{...e,result:{content:[{type:"text",text:`define_local_identity_file failed: ${u instanceof Error?u.message:String(u)}`}],isError:!0}}}}if(o?.name!=="save_file")return e;let i=e.result,s=i?.structuredContent?.oursHostSave;if(i?.isError===!0||!s)return e;let d=o.arguments?.wire_id,R=o.arguments?.dest_path;if(s.wire_id!==d||s.dest_path!==R||typeof s.wire_id!="string"||typeof s.dest_path!="string")throw new Error("save_file returned a host intent that does not match the request.");try{let f=t.openFile(s.wire_id),p=n?await new Promise((ot,T)=>{let H=!1,_=()=>{H=!0,T($(n))};n.addEventListener("abort",_,{once:!0}),f.then(v=>{n.removeEventListener("abort",_),H?v.cancel().catch(()=>{}):ot(v)},v=>{n.removeEventListener("abort",_),T(v)})}):await f;g(n);let c=q(s.dest_path);yt(gt(c),{recursive:!0});let y=G.fromWeb(p),u=mt(c);n?await j(y,u,{signal:n}):await j(y,u),g(n);let N=L(c).size;return{...e,result:{content:[{type:"text",text:`Saved file (wire_id ${s.wire_id}) to ${c} (${N} bytes). The bytes were streamed daemon\u2192disk and never entered this result.`}],isError:!1}}}catch(f){return g(n),{...e,result:{content:[{type:"text",text:`save_file failed: ${f instanceof Error?f.message:String(f)}`}],isError:!0}}}}import{createHash as $t,randomUUID as B}from"node:crypto";import{chmod as K,mkdir as kt,readFile as Ft,rename as Tt,unlink as Ht,writeFile as Jt}from"node:fs/promises";import{dirname as Ut,join as Dt,resolve as jt}from"node:path";import{attachOursClient as Lt}from"@ours.network/sdk";import{createHash as Pt}from"node:crypto";import{openSync as xt,closeSync as Rt,lstatSync as k,mkdirSync as Nt,chmodSync as _t,constants as E}from"node:fs";import{join as M}from"node:path";import{createRequire as z}from"node:module";var Ot=5e3,h=null,V=!1;function Ct(){if(h)return h;if(V)throw new Error("No SQLite implementation available for native session guard");V=!0;try{return h=z(import.meta.url)("node:sqlite").DatabaseSync,h}catch{try{let t=z(import.meta.url)("better-sqlite3");return h=t.default??t,h}catch{throw new Error("Native session guard requires node:sqlite (Node >=22.13) or better-sqlite3")}}}function At(t){try{let e=xt(t,E.O_RDWR|E.O_CREAT|E.O_EXCL|E.O_NOFOLLOW,384);Rt(e)}catch(e){if(e.code!=="EEXIST")throw e}let r=k(t);if(!r.isFile()||r.uid!==process.getuid()||r.mode&63||r.nlink!==1)throw new Error("Native session guard file must be an owner-only regular file")}function Y(t){let r=process.getuid(),e=M(`/tmp/ours-${r}`,"session-guards");Nt(e,{recursive:!0,mode:448});try{_t(e,448)}catch{}let n=Pt("sha256").update(t).digest("hex"),o=M(e,`${n}.guard`);At(o);let i=k(o),a=Ct(),s=new a(o);try{let d=k(o);if(i.dev!==d.dev||i.ino!==d.ino||i.mode!==d.mode||i.uid!==d.uid)throw new Error("Native session guard file changed during acquisition");return s.exec(`PRAGMA busy_timeout=${Ot}; BEGIN EXCLUSIVE`),()=>{try{s.close()}catch{}}}catch(d){try{s.close()}catch{}throw d}}var P=1,Q=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/,m=new Map,S=new Map;function qt(t){if(typeof t!="string"||t.length===0||t.length>4096||t.trim()!==t||t.includes("\0"))throw new Error("Native session metadata is missing or invalid for this host-profile tool call.");return t}function x(t,r,e){if(!t||!t.startsWith("/")||jt(t)!==t)throw new Error("Native session host record root must be a normalized absolute path.");if(!Q.test(r))throw new Error("Native session daemon instance must be a lowercase UUID.");let n=$t("sha256").update(qt(e),"utf8").digest("hex");return Dt(t,"sessions",r,`${n}.json`)}function Gt(t,r){let e;try{e=JSON.parse(t)}catch(i){throw new Error(`Invalid native session record at ${r}: ${String(i)}`)}if(!e||typeof e!="object"||Array.isArray(e))throw new Error(`Invalid native session record at ${r}: expected an object.`);let n=e;if(Object.keys(n).sort().join(",")!=="ownerInstanceId,state,version"||n.version!==P||typeof n.ownerInstanceId!="string"||!Q.test(n.ownerInstanceId)||!["active","pending","ended"].includes(String(n.state)))throw new Error(`Invalid native session record at ${r}.`);return n}async function b(t){try{return Gt(await Ft(t,"utf8"),t)}catch(r){if(r.code==="ENOENT")return null;throw r}}async function F(t,r){let e=Ut(t);await kt(e,{recursive:!0,mode:448}),await K(e,448);let n=`${t}.${process.pid}.${B()}.tmp`;try{await Jt(n,`${JSON.stringify(r,null,2)}
|
|
3
|
+
`,{mode:384,flag:"wx"}),await Tt(n,t),await K(t,384)}catch(o){try{await Ht(n)}catch{}throw o}}async function Z(t,r){let e=S.get(t)??Promise.resolve(),n,o=new Promise(s=>{n=s}),i=e.catch(()=>{}).then(()=>o);S.set(t,i),await e.catch(()=>{});let a;try{return a=Y(t),await r()}finally{try{a?.()}finally{n(),S.get(t)===i&&S.delete(t)}}}function tt(t,r){return Lt({endpoint:t.endpoint,expectedInstanceId:t.expectedInstanceId,credentialPath:t.credentialPath,sessionMode:"external",leaseToken:r,env:{}})}function X(t,r,e){let n=m.get(t);if(n?.ownerInstanceId===e)return n.promise;n&&(m.delete(t),n.promise.then(a=>a.close()).catch(()=>{}));let o=tt(r,e),i={ownerInstanceId:e,promise:o};return m.set(t,i),o.catch(()=>{m.get(t)===i&&m.delete(t)}),o}async function Wt(t,r,e){let n=m.get(t),o=n?.ownerInstanceId===e?await n.promise:await tt(r,e);try{await o.releaseLease()}finally{n?.ownerInstanceId!==e&&await o.close()}}async function et(t,r,e){await Wt(t,r,e);let n=await b(t);n?.state==="pending"&&n.ownerInstanceId===e&&await F(t,{version:P,ownerInstanceId:e,state:"ended"});let o=m.get(t);o?.ownerInstanceId===e&&(m.delete(t),o.promise.then(i=>i.close()).catch(()=>{}))}async function nt(t,r,e){let n=w(t),o=x(e,n.expectedInstanceId,r);return Z(o,async()=>{let i=await b(o);if(i?.state==="pending"&&(await et(o,n,i.ownerInstanceId),i=await b(o)),i?.state==="active")return X(o,n,i.ownerInstanceId);let a=B();return await F(o,{version:P,ownerInstanceId:a,state:"active"}),X(o,n,a)})}async function rt(t,r,e){let n=w(t),o=x(e,n.expectedInstanceId,r);await Z(o,async()=>{let i=await b(o);i===null||i.state==="ended"||(i.state==="active"&&(i={version:P,ownerInstanceId:i.ownerInstanceId,state:"pending"},await F(o,i)),await et(o,n,i.ownerInstanceId))})}export{bt as completeHostFileCall,rt as endNativeSessionAtRoot,D as hostProfileFromEnv,A as hostProfileSelectionFromEnv,nt as nativeClientForAtRoot,x as nativeSessionRecordPath,St as prepareHostFileCall,C as readHostProfile,w as validateHostProfile};
|
package/dist/host-profile.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{existsSync as h,lstatSync as u,readFileSync as g}from"node:fs";import{homedir as d}from"node:os";import{resolve as l}from"node:path";var p=["endpoint","expectedInstanceId","credentialPath"],m=["port","stateDir","apiToken","apiVisibility"],w=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/,y=["OURS_API_TOKEN","OURS_PORT","OURS_STATE_DIR","OURS_DAEMON_ID"];function
|
|
1
|
+
import{existsSync as h,lstatSync as u,readFileSync as g}from"node:fs";import{homedir as d}from"node:os";import{resolve as l}from"node:path";var p=["endpoint","expectedInstanceId","credentialPath"],m=["port","stateDir","apiToken","apiVisibility"],w=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/,y=["OURS_API_TOKEN","OURS_PORT","OURS_STATE_DIR","OURS_DAEMON_ID"];function n(t){return new Error(`Invalid external host profile: ${t}`)}function O(t){if(!t||typeof t!="object"||Array.isArray(t))throw n("expected a complete host profile object.");let e=t;if(p.filter(f=>Object.hasOwn(e,f)).length!==p.length)throw n("expected a complete host profile tuple: endpoint, expectedInstanceId, credentialPath.");let o=m.filter(f=>Object.hasOwn(e,f));if(o.length)throw n(`legacy selection keys cannot be mixed with a host profile (${o.join(", ")}).`);let c=e.endpoint,a=e.expectedInstanceId,i=e.credentialPath;if(typeof c!="string"||c.trim()!==c||c==="")throw n("endpoint must be a non-empty HTTP or HTTPS origin.");if(typeof a!="string"||!w.test(a))throw n("expectedInstanceId must be a lowercase UUID.");if(typeof i!="string"||i===""||!i.startsWith("/")||l(i)!==i)throw n("credentialPath must be a normalized absolute path.");let s;try{s=new URL(c)}catch{throw n("endpoint must be an HTTP or HTTPS origin.")}if(s.protocol!=="http:"&&s.protocol!=="https:"||s.username||s.password||s.pathname!=="/"||s.search||s.hash)throw n("endpoint must be an HTTP or HTTPS origin without credentials, path, query, or fragment.");return{endpoint:s.origin,expectedInstanceId:a,credentialPath:i}}function S(t){let e;try{e=g(t,"utf8")}catch{throw new Error(`Cannot read host profile ${JSON.stringify(t)}.`)}let r;try{r=JSON.parse(e)}catch{throw n(`config ${JSON.stringify(t)} is not valid JSON.`)}if(!r||typeof r!="object"||Array.isArray(r))throw n(`config ${JSON.stringify(t)} must be an object.`);return r}function E(t){let e;try{e=u(t)}catch{throw new Error(`Cannot read host profile ${JSON.stringify(t)}.`)}if(!e.isFile())throw n(`config ${JSON.stringify(t)} must be a regular file.`);let r=process.getuid?.();if(r===void 0||e.uid!==r)throw n(`config ${JSON.stringify(t)} must be owned by the current user.`);if(e.mode&63)throw n(`config ${JSON.stringify(t)} must have private permissions.`)}function P(t){let e=S(t);return p.filter(o=>Object.hasOwn(e,o)).length===0?null:(E(t),O(e))}function I(t,e){return(t[e]??"").trim()!==""}function N(t=process.env){let e=(t.OURS_CONFIG??"").trim(),r=l(t.HOME||d(),".ours-client","profile.json"),o=e;if(!o)try{u(r),o=r}catch(i){if(i.code!=="ENOENT")throw new Error(`Cannot read host profile ${JSON.stringify(r)}.`);if(o=l(d(),".ours","config.json"),!h(o))return null}let c=P(o);if(c===null){if(l(o)===r)throw n("managed client config must contain a complete host profile tuple.");return null}let a=y.filter(i=>I(t,i));if(a.length)throw n(`${a.join(", ")} conflicts with host-profile mode.`);return{profile:c,configPath:o}}function R(t=process.env){return N(t)?.profile??null}export{R as hostProfileFromEnv,N as hostProfileSelectionFromEnv,P as readHostProfile,O as validateHostProfile};
|
package/dist/native-session.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{createHash as z,randomUUID as $}from"node:crypto";import{chmod as x,mkdir as K,readFile as X,rename as B,unlink as Q,writeFile as Z}from"node:fs/promises";import{dirname as I,join as tt,resolve as et}from"node:path";import{attachOursClient as nt}from"@ours.network/sdk";import{homedir as U}from"node:os";import{dirname as lt,resolve as E}from"node:path";var _="OURS_MCP_CONFIG";function w(t=process.env){let e=(t[_]??"").trim();return E(e||E(U(),".ours-mcp","config.json"))}import{resolve as j}from"node:path";var S=["endpoint","expectedInstanceId","credentialPath"],J=["port","stateDir","apiToken","apiVisibility"],H=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;function d(t){return new Error(`Invalid external host profile: ${t}`)}function y(t){if(!t||typeof t!="object"||Array.isArray(t))throw d("expected a complete host profile object.");let e=t;if(S.filter(c=>Object.hasOwn(e,c)).length!==S.length)throw d("expected a complete host profile tuple: endpoint, expectedInstanceId, credentialPath.");let i=J.filter(c=>Object.hasOwn(e,c));if(i.length)throw d(`legacy selection keys cannot be mixed with a host profile (${i.join(", ")}).`);let r=e.endpoint,o=e.expectedInstanceId,s=e.credentialPath;if(typeof r!="string"||r.trim()!==r||r==="")throw d("endpoint must be a non-empty HTTP origin.");if(typeof o!="string"||!H.test(o))throw d("expectedInstanceId must be a lowercase UUID.");if(typeof s!="string"||s===""||!s.startsWith("/")||j(s)!==s)throw d("credentialPath must be a normalized absolute path.");let a;try{a=new URL(r)}catch{throw d("endpoint must be an HTTP origin.")}if(a.protocol!=="http:"||a.username||a.password||a.pathname!=="/"||a.search||a.hash)throw d("endpoint must be an HTTP origin without credentials, path, query, or fragment.");return{endpoint:a.origin,expectedInstanceId:o,credentialPath:s}}import{createHash as L}from"node:crypto";import{openSync as F,closeSync as q,lstatSync as h,mkdirSync as G,chmodSync as M,constants as
|
|
2
|
-
`,{mode:384,flag:"wx"}),await B(i,t),await x(t,384)}catch(r){try{await Q(i)}catch{}throw r}}async function
|
|
1
|
+
import{createHash as z,randomUUID as $}from"node:crypto";import{chmod as x,mkdir as K,readFile as X,rename as B,unlink as Q,writeFile as Z}from"node:fs/promises";import{dirname as I,join as tt,resolve as et}from"node:path";import{attachOursClient as nt}from"@ours.network/sdk";import{homedir as U}from"node:os";import{dirname as lt,resolve as E}from"node:path";var _="OURS_MCP_CONFIG";function w(t=process.env){let e=(t[_]??"").trim();return E(e||E(U(),".ours-mcp","config.json"))}import{resolve as j}from"node:path";var S=["endpoint","expectedInstanceId","credentialPath"],J=["port","stateDir","apiToken","apiVisibility"],H=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;function d(t){return new Error(`Invalid external host profile: ${t}`)}function y(t){if(!t||typeof t!="object"||Array.isArray(t))throw d("expected a complete host profile object.");let e=t;if(S.filter(c=>Object.hasOwn(e,c)).length!==S.length)throw d("expected a complete host profile tuple: endpoint, expectedInstanceId, credentialPath.");let i=J.filter(c=>Object.hasOwn(e,c));if(i.length)throw d(`legacy selection keys cannot be mixed with a host profile (${i.join(", ")}).`);let r=e.endpoint,o=e.expectedInstanceId,s=e.credentialPath;if(typeof r!="string"||r.trim()!==r||r==="")throw d("endpoint must be a non-empty HTTP or HTTPS origin.");if(typeof o!="string"||!H.test(o))throw d("expectedInstanceId must be a lowercase UUID.");if(typeof s!="string"||s===""||!s.startsWith("/")||j(s)!==s)throw d("credentialPath must be a normalized absolute path.");let a;try{a=new URL(r)}catch{throw d("endpoint must be an HTTP or HTTPS origin.")}if(a.protocol!=="http:"&&a.protocol!=="https:"||a.username||a.password||a.pathname!=="/"||a.search||a.hash)throw d("endpoint must be an HTTP or HTTPS origin without credentials, path, query, or fragment.");return{endpoint:a.origin,expectedInstanceId:o,credentialPath:s}}import{createHash as L}from"node:crypto";import{openSync as F,closeSync as q,lstatSync as h,mkdirSync as G,chmodSync as M,constants as p}from"node:fs";import{join as P}from"node:path";import{createRequire as N}from"node:module";var V=5e3,f=null,O=!1;function W(){if(f)return f;if(O)throw new Error("No SQLite implementation available for native session guard");O=!0;try{return f=N(import.meta.url)("node:sqlite").DatabaseSync,f}catch{try{let t=N(import.meta.url)("better-sqlite3");return f=t.default??t,f}catch{throw new Error("Native session guard requires node:sqlite (Node >=22.13) or better-sqlite3")}}}function Y(t){try{let n=F(t,p.O_RDWR|p.O_CREAT|p.O_EXCL|p.O_NOFOLLOW,384);q(n)}catch(n){if(n.code!=="EEXIST")throw n}let e=h(t);if(!e.isFile()||e.uid!==process.getuid()||e.mode&63||e.nlink!==1)throw new Error("Native session guard file must be an owner-only regular file")}function b(t){let e=process.getuid(),n=P(`/tmp/ours-${e}`,"session-guards");G(n,{recursive:!0,mode:448});try{M(n,448)}catch{}let i=L("sha256").update(t).digest("hex"),r=P(n,`${i}.guard`);Y(r);let o=h(r),s=W(),a=new s(r);try{let c=h(r);if(o.dev!==c.dev||o.ino!==c.ino||o.mode!==c.mode||o.uid!==c.uid)throw new Error("Native session guard file changed during acquisition");return a.exec(`PRAGMA busy_timeout=${V}; BEGIN EXCLUSIVE`),()=>{try{a.close()}catch{}}}catch(c){try{a.close()}catch{}throw c}}var m=1,R=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/,l=new Map,u=new Map;function it(t){if(typeof t!="string"||t.length===0||t.length>4096||t.trim()!==t||t.includes("\0"))throw new Error("Native session metadata is missing or invalid for this host-profile tool call.");return t}function T(t,e,n){if(!t||!t.startsWith("/")||et(t)!==t)throw new Error("Native session host record root must be a normalized absolute path.");if(!R.test(e))throw new Error("Native session daemon instance must be a lowercase UUID.");let i=z("sha256").update(it(n),"utf8").digest("hex");return tt(t,"sessions",e,`${i}.json`)}function rt(t,e){let n;try{n=JSON.parse(t)}catch(o){throw new Error(`Invalid native session record at ${e}: ${String(o)}`)}if(!n||typeof n!="object"||Array.isArray(n))throw new Error(`Invalid native session record at ${e}: expected an object.`);let i=n;if(Object.keys(i).sort().join(",")!=="ownerInstanceId,state,version"||i.version!==m||typeof i.ownerInstanceId!="string"||!R.test(i.ownerInstanceId)||!["active","pending","ended"].includes(String(i.state)))throw new Error(`Invalid native session record at ${e}.`);return i}async function g(t){try{return rt(await X(t,"utf8"),t)}catch(e){if(e.code==="ENOENT")return null;throw e}}async function v(t,e){let n=I(t);await K(n,{recursive:!0,mode:448}),await x(n,448);let i=`${t}.${process.pid}.${$()}.tmp`;try{await Z(i,`${JSON.stringify(e,null,2)}
|
|
2
|
+
`,{mode:384,flag:"wx"}),await B(i,t),await x(t,384)}catch(r){try{await Q(i)}catch{}throw r}}async function A(t,e){let n=u.get(t)??Promise.resolve(),i,r=new Promise(a=>{i=a}),o=n.catch(()=>{}).then(()=>r);u.set(t,o),await n.catch(()=>{});let s;try{return s=b(t),await e()}finally{try{s?.()}finally{i(),u.get(t)===o&&u.delete(t)}}}function k(t,e){return nt({endpoint:t.endpoint,expectedInstanceId:t.expectedInstanceId,credentialPath:t.credentialPath,sessionMode:"external",leaseToken:e,env:{}})}function C(t,e,n){let i=l.get(t);if(i?.ownerInstanceId===n)return i.promise;i&&(l.delete(t),i.promise.then(s=>s.close()).catch(()=>{}));let r=k(e,n),o={ownerInstanceId:n,promise:r};return l.set(t,o),r.catch(()=>{l.get(t)===o&&l.delete(t)}),r}async function ot(t,e,n){let i=l.get(t),r=i?.ownerInstanceId===n?await i.promise:await k(e,n);try{await r.releaseLease()}finally{i?.ownerInstanceId!==n&&await r.close()}}async function D(t,e,n){await ot(t,e,n);let i=await g(t);i?.state==="pending"&&i.ownerInstanceId===n&&await v(t,{version:m,ownerInstanceId:n,state:"ended"});let r=l.get(t);r?.ownerInstanceId===n&&(l.delete(t),r.promise.then(o=>o.close()).catch(()=>{}))}async function bt(t,e,n=process.env){return st(t,e,I(w(n)))}async function st(t,e,n){let i=y(t),r=T(n,i.expectedInstanceId,e);return A(r,async()=>{let o=await g(r);if(o?.state==="pending"&&(await D(r,i,o.ownerInstanceId),o=await g(r)),o?.state==="active")return C(r,i,o.ownerInstanceId);let s=$();return await v(r,{version:m,ownerInstanceId:s,state:"active"}),C(r,i,s)})}async function xt(t,e,n=process.env){return at(t,e,I(w(n)))}async function at(t,e,n){let i=y(t),r=T(n,i.expectedInstanceId,e);await A(r,async()=>{let o=await g(r);o===null||o.state==="ended"||(o.state==="active"&&(o={version:m,ownerInstanceId:o.ownerInstanceId,state:"pending"},await v(r,o)),await D(r,i,o.ownerInstanceId))})}export{xt as endNativeSession,at as endNativeSessionAtRoot,bt as nativeClientFor,st as nativeClientForAtRoot,T as nativeSessionRecordPath};
|
|
@@ -48,7 +48,7 @@ data:
|
|
|
48
48
|
`),s+=`data: ${JSON.stringify(n)}
|
|
49
49
|
|
|
50
50
|
`,e.enqueue(r.encode(s)),!0}catch(s){return this.onerror?.(s),!1}}handleUnsupportedRequest(){return this.onerror?.(new Error("Method not allowed.")),new Response(JSON.stringify({jsonrpc:"2.0",error:{code:-32e3,message:"Method not allowed."},id:null}),{status:405,headers:{Allow:"GET, POST, DELETE","Content-Type":"application/json"}})}async handlePostRequest(e,r){try{let n=e.headers.get("accept");if(!n?.includes("application/json")||!n.includes("text/event-stream"))return this.onerror?.(new Error("Not Acceptable: Client must accept both application/json and text/event-stream")),this.createJsonErrorResponse(406,-32e3,"Not Acceptable: Client must accept both application/json and text/event-stream");let o=e.headers.get("content-type");if(!o||!o.includes("application/json"))return this.onerror?.(new Error("Unsupported Media Type: Content-Type must be application/json")),this.createJsonErrorResponse(415,-32e3,"Unsupported Media Type: Content-Type must be application/json");let s={headers:Object.fromEntries(e.headers.entries()),url:new URL(e.url)},i;if(r?.parsedBody!==void 0)i=r.parsedBody;else try{i=await e.json()}catch{return this.onerror?.(new Error("Parse error: Invalid JSON")),this.createJsonErrorResponse(400,-32700,"Parse error: Invalid JSON")}let a;try{Array.isArray(i)?a=i.map(v=>Ss.parse(v)):a=[Ss.parse(i)]}catch{return this.onerror?.(new Error("Parse error: Invalid JSON-RPC message")),this.createJsonErrorResponse(400,-32700,"Parse error: Invalid JSON-RPC message")}let c=a.some(eo);if(c){if(this._initialized&&this.sessionId!==void 0)return this.onerror?.(new Error("Invalid Request: Server already initialized")),this.createJsonErrorResponse(400,-32600,"Invalid Request: Server already initialized");if(a.length>1)return this.onerror?.(new Error("Invalid Request: Only one initialization request is allowed")),this.createJsonErrorResponse(400,-32600,"Invalid Request: Only one initialization request is allowed");this.sessionId=this.sessionIdGenerator?.(),this._initialized=!0,this.sessionId&&this._onsessioninitialized&&await Promise.resolve(this._onsessioninitialized(this.sessionId))}if(!c){let v=this.validateSession(e);if(v)return v;let b=this.validateProtocolVersion(e);if(b)return b}if(!a.some(Ft)){for(let v of a)this.onmessage?.(v,{authInfo:r?.authInfo,requestInfo:s});return new Response(null,{status:202})}let l=crypto.randomUUID(),d=a.find(v=>eo(v)),f=d?d.params.protocolVersion:e.headers.get("mcp-protocol-version")??oh;if(this._enableJsonResponse)return new Promise(v=>{this._streamMapping.set(l,{resolveJson:v,cleanup:()=>{this._streamMapping.delete(l)}});for(let b of a)Ft(b)&&this._requestToStreamMapping.set(b.id,l);for(let b of a)this.onmessage?.(b,{authInfo:r?.authInfo,requestInfo:s})});let m=new TextEncoder,p,h=new ReadableStream({start:v=>{p=v},cancel:()=>{this._streamMapping.delete(l)}}),g={"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"};this.sessionId!==void 0&&(g["mcp-session-id"]=this.sessionId);for(let v of a)Ft(v)&&(this._streamMapping.set(l,{controller:p,encoder:m,cleanup:()=>{this._streamMapping.delete(l);try{p.close()}catch{}}}),this._requestToStreamMapping.set(v.id,l));await this.writePrimingEvent(p,m,l,f);for(let v of a){let b,$;Ft(v)&&this._eventStore&&f>="2025-11-25"&&(b=()=>{this.closeSSEStream(v.id)},$=()=>{this.closeStandaloneSSEStream()}),this.onmessage?.(v,{authInfo:r?.authInfo,requestInfo:s,closeSSEStream:b,closeStandaloneSSEStream:$})}return new Response(h,{status:200,headers:g})}catch(n){return this.onerror?.(n),this.createJsonErrorResponse(400,-32700,"Parse error",{data:String(n)})}}async handleDeleteRequest(e){let r=this.validateSession(e);if(r)return r;let n=this.validateProtocolVersion(e);return n||(await Promise.resolve(this._onsessionclosed?.(this.sessionId)),await this.close(),new Response(null,{status:200}))}validateSession(e){if(this.sessionIdGenerator===void 0)return;if(!this._initialized)return this.onerror?.(new Error("Bad Request: Server not initialized")),this.createJsonErrorResponse(400,-32e3,"Bad Request: Server not initialized");let r=e.headers.get("mcp-session-id");if(!r)return this.onerror?.(new Error("Bad Request: Mcp-Session-Id header is required")),this.createJsonErrorResponse(400,-32e3,"Bad Request: Mcp-Session-Id header is required");if(r!==this.sessionId)return this.onerror?.(new Error("Session not found")),this.createJsonErrorResponse(404,-32001,"Session not found")}validateProtocolVersion(e){let r=e.headers.get("mcp-protocol-version");if(r!==null&&!rn.includes(r))return this.onerror?.(new Error(`Bad Request: Unsupported protocol version: ${r} (supported versions: ${rn.join(", ")})`)),this.createJsonErrorResponse(400,-32e3,`Bad Request: Unsupported protocol version: ${r} (supported versions: ${rn.join(", ")})`)}async close(){this._streamMapping.forEach(({cleanup:e})=>{e()}),this._streamMapping.clear(),this._requestResponseMap.clear(),this.onclose?.()}closeSSEStream(e){let r=this._requestToStreamMapping.get(e);if(!r)return;let n=this._streamMapping.get(r);n&&n.cleanup()}closeStandaloneSSEStream(){let e=this._streamMapping.get(this._standaloneSseStreamId);e&&e.cleanup()}async send(e,r){let n=r?.relatedRequestId;if((It(e)||nn(e))&&(n=e.id),n===void 0){if(It(e)||nn(e))throw new Error("Cannot send a response on a standalone SSE stream unless resuming a previous client request");let i;this._eventStore&&(i=await this._eventStore.storeEvent(this._standaloneSseStreamId,e));let a=this._streamMapping.get(this._standaloneSseStreamId);if(a===void 0)return;a.controller&&a.encoder&&this.writeSSEEvent(a.controller,a.encoder,e,i);return}let o=this._requestToStreamMapping.get(n);if(!o)throw new Error(`No connection established for request ID: ${String(n)}`);let s=this._streamMapping.get(o);if(!this._enableJsonResponse&&s?.controller&&s?.encoder){let i;this._eventStore&&(i=await this._eventStore.storeEvent(o,e)),this.writeSSEEvent(s.controller,s.encoder,e,i)}if(It(e)||nn(e)){this._requestResponseMap.set(n,e);let i=Array.from(this._requestToStreamMapping.entries()).filter(([c,u])=>u===o).map(([c])=>c);if(i.every(c=>this._requestResponseMap.has(c))){if(!s)throw new Error(`No connection established for request ID: ${String(n)}`);if(this._enableJsonResponse&&s.resolveJson){let c={"Content-Type":"application/json"};this.sessionId!==void 0&&(c["mcp-session-id"]=this.sessionId);let u=i.map(l=>this._requestResponseMap.get(l));u.length===1?s.resolveJson(new Response(JSON.stringify(u[0]),{status:200,headers:c})):s.resolveJson(new Response(JSON.stringify(u),{status:200,headers:c}))}else s.cleanup();for(let c of i)this._requestResponseMap.delete(c),this._requestToStreamMapping.delete(c)}}}};var Hs=class{constructor(e={}){this._requestContext=new WeakMap,this._webStandardTransport=new Vs(e),this._requestListener=ya(async r=>{let n=this._requestContext.get(r);return this._webStandardTransport.handleRequest(r,{authInfo:n?.authInfo,parsedBody:n?.parsedBody})},{overrideGlobalObjects:!1})}get sessionId(){return this._webStandardTransport.sessionId}set onclose(e){this._webStandardTransport.onclose=e}get onclose(){return this._webStandardTransport.onclose}set onerror(e){this._webStandardTransport.onerror=e}get onerror(){return this._webStandardTransport.onerror}set onmessage(e){this._webStandardTransport.onmessage=e}get onmessage(){return this._webStandardTransport.onmessage}async start(){return this._webStandardTransport.start()}async close(){return this._webStandardTransport.close()}async send(e,r){return this._webStandardTransport.send(e,r)}async handleRequest(e,r,n){let o=e.auth;await ya(async i=>this._webStandardTransport.handleRequest(i,{authInfo:o,parsedBody:n}),{overrideGlobalObjects:!1})(e,r)}closeSSEStream(e){this._webStandardTransport.closeSSEStream(e)}closeStandaloneSSEStream(){this._webStandardTransport.closeStandaloneSSEStream()}};Vt();import{attachOursClient as WR}from"@ours.network/sdk";import{randomUUID as x$}from"node:crypto";import{chmod as $$,mkdir as S$,readFile as k$,rename as T$,unlink as z$,writeFile as E$}from"node:fs/promises";import{homedir as P$}from"node:os";import{dirname as I$,resolve as co}from"node:path";var bh=1,R$="OURS_MCP_CONFIG",$h=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/,O$=()=>({version:1,daemons:{},instances:{}});function Sh(t=process.env){let e=(t[R$]??"").trim();return co(e||co(P$(),".ours-mcp","config.json"))}function wh(t,e,r,n){if(!t||typeof t!="object"||Array.isArray(t))throw new Error(`Invalid ours-mcp application identity config at ${e}: "${r}s" must be an object.`);let o={};for(let[s,i]of Object.entries(t)){if(!i||typeof i!="object"||Array.isArray(i))throw new Error(`Invalid ours-mcp application identity config at ${e}: ${r} ${JSON.stringify(s)} must be an object.`);let a=i;if(!Array.isArray(a.identities)||a.identities.some(c=>typeof c!="string"||c.length===0))throw new Error(`Invalid ours-mcp application identity config at ${e}: ${r} ${JSON.stringify(s)} has an invalid identity list.`);o[n(s)]={identities:[...new Set(a.identities)].sort()}}return o}function C$(t,e){let r;try{r=JSON.parse(t)}catch(i){throw new Error(`Invalid ours-mcp application identity config at ${e}: ${String(i)}`)}if(!r||typeof r!="object"||Array.isArray(r))throw new Error(`Invalid ours-mcp application identity config at ${e}: expected an object.`);let n=r;if(n.version!==bh)throw new Error(`Unsupported ours-mcp application identity config version at ${e}: expected ${bh}, found ${String(n.version)}.`);let o=wh(n.daemons,e,"daemon",co),s=n.instances===void 0?{}:wh(n.instances,e,"instance",i=>{if(!$h.test(i))throw new Error(`Invalid ours-mcp application identity config at ${e}: instance ${JSON.stringify(i)} must be a lowercase UUID.`);return i});return{version:1,daemons:o,instances:s}}async function Gu(t){try{return C$(await k$(t,"utf8"),t)}catch(e){if(e.code==="ENOENT")return O$();throw e}}async function xh(t,e){let r=I$(t);await S$(r,{recursive:!0,mode:448});let n=`${t}.${process.pid}.${x$()}.tmp`;try{await E$(n,`${JSON.stringify(e,null,2)}
|
|
51
|
-
`,{mode:384,flag:"wx"}),await T$(n,t),await $$(t,384)}catch(o){try{await z$(n)}catch{}throw o}}var uo=class{stateDir;instanceId;path;constructor(e,r={}){if(typeof e=="string")this.stateDir=co(e),this.instanceId=null;else{if(!e||!$h.test(e.instanceId))throw new Error("Application identity instanceId must be a lowercase UUID.");this.stateDir=null,this.instanceId=e.instanceId}this.path=co(r.path??Sh(r.env))}rows(e){return this.instanceId===null?e.daemons:e.instances}key(){return this.instanceId??this.stateDir}async list(){let e=await Gu(this.path);return[...this.rows(e)[this.key()]?.identities??[]]}async has(e){return(await this.list()).includes(e)}async add(e){if(!e)throw new Error("Cannot add an empty identity name to ours-mcp.");let r=await Gu(this.path),n=this.rows(r),o=this.key(),s=n[o]?.identities??[];s.includes(e)||(n[o]={identities:[...s,e].sort()},await xh(this.path,r))}async remove(e){let r=await Gu(this.path),n=this.rows(r),o=this.key(),s=n[o];if(!s?.identities.includes(e))return;let i=s.identities.filter(a=>a!==e);i.length===0?delete n[o]:n[o]={identities:i},await xh(this.path,r)}};async function kh(t,e){let r=new Set(await t.list());return e.filter(n=>r.has(n.name))}Vt();import{attachOursClient as kD,OursError as TD,resolveDaemonConfig as zD}from"@ours.network/sdk";import{resolve as N$}from"node:path";var Th=["endpoint","expectedInstanceId","credentialPath"],A$=["port","stateDir","apiToken","apiVisibility"],j$=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;function Ht(t){return new Error(`Invalid external host profile: ${t}`)}function Bs(t){if(!t||typeof t!="object"||Array.isArray(t))throw Ht("expected a complete host profile object.");let e=t;if(Th.filter(c=>Object.hasOwn(e,c)).length!==Th.length)throw Ht("expected a complete host profile tuple: endpoint, expectedInstanceId, credentialPath.");let n=A$.filter(c=>Object.hasOwn(e,c));if(n.length)throw Ht(`legacy selection keys cannot be mixed with a host profile (${n.join(", ")}).`);let o=e.endpoint,s=e.expectedInstanceId,i=e.credentialPath;if(typeof o!="string"||o.trim()!==o||o==="")throw Ht("endpoint must be a non-empty HTTP origin.");if(typeof s!="string"||!j$.test(s))throw Ht("expectedInstanceId must be a lowercase UUID.");if(typeof i!="string"||i===""||!i.startsWith("/")||N$(i)!==i)throw Ht("credentialPath must be a normalized absolute path.");let a;try{a=new URL(o)}catch{throw Ht("endpoint must be an HTTP origin.")}if(a.protocol!=="http:"||a.username||a.password||a.pathname!=="/"||a.search||a.hash)throw Ht("endpoint must be an HTTP origin without credentials, path, query, or fragment.");return{endpoint:a.origin,expectedInstanceId:s,credentialPath:i}}import{attachOursClient as FC}from"@ours.network/sdk";Xv();Dt();import{OursError as Lp}from"@ours.network/sdk";function L(t,e=!1){return{content:[{type:"text",text:t}],isError:e}}var Up=new WeakMap;function Qv(t,e){Up.set(t,e)}function Wo(t){return Up.get(t)??null}function $R(t){Up.delete(t)}async function SR(t){let e=Wo(t);if(!e)return!1;try{return await t.chooseIdentity({name:e,force:!1}),!0}catch{return $R(t),!1}}async function W(t,e,r){let n=await t,o;try{o=await e(n)}catch(s){if(s instanceof Lp&&s.code==="NOT_BOUND"&&await SR(n))try{return r(await e(n))}catch(i){if(i instanceof Lp)return L(i.message,!0);throw i}if(s instanceof Lp)return L(s.message,!0);throw s}return Wo(n)===null&&n.currentIdentity().then(s=>{Qv(n,s.name)}).catch(()=>{}),r(o)}var Fp=k.lazy(()=>k.union([k.null(),k.boolean(),k.number(),k.string(),k.array(Fp),k.record(Fp)]));function eb(t,e){t.tool("list_contact_commands","List the typed commands a contact currently advertises. The returned catalog is data; remote commands are not registered as MCP tools.",{contact:k.string().min(1).describe("Contact name or container id.")},async({contact:r},n)=>W(e(n),o=>o.listContactCommands({contact:r}),o=>{let s={contact:r,count:o.length,commands:o};return{content:[{type:"text",text:JSON.stringify(s,null,2)}],structuredContent:s,isError:!1}})),t.tool("send_command","Send a typed command to a contact after the SDK validates it against that contact's advertised schema. Use get_messages to retrieve a correlated command_result whose reply_to.wire_id matches request_wire_id.",{contact:k.string().min(1).describe("Contact name or container id."),command:k.string().min(1).describe("Advertised command name."),arguments:Fp.describe("Any JSON-compatible command arguments accepted by the advertised schema.")},async({contact:r,command:n,arguments:o},s)=>W(e(s),i=>i.sendCommand({contact:r,command:n,arguments:o}),i=>{let a={request_wire_id:i.wireId,outcome:i};return{content:[{type:"text",text:JSON.stringify(a,null,2)}],structuredContent:a,isError:i.kind==="refused"}}))}Dt();function kR(t){let e=new Map;for(let r of t)e.set(r.name,(e.get(r.name)??0)+1);return e}function tb(t){let e=kR(t);return t.map(r=>`\u2022 ${r.name} \u2014 ${r.container_id}${r.rootTag??""}${r.degradedQueued!==void 0?` \u2014 \u26A0 keys pending restore (${r.degradedQueued} queued)`:""}${(e.get(r.name)??0)>1?" \u2014 \u26A0 DUPLICATE NAME: sends to this name abort; address by container id, repair with rename_contact":""}${r.renamedFrom!==void 0?` \u2014 \u26A0 renamed on import (two contacts were named "${r.renamedFrom}"; do NOT assume the one keeping the bare name is the live one \u2014 verify by container id, settle with rename_contact)`:""}`)}function TR(t){if(!t)return"";let e=t.root_name||t.root_cid;return t.role_id?` [role "${t.role_id}" of ${e}]`:` [root identity of ${e}]`}function rb(t,e){t.tool("generate_invite",'Generate an invite to share out-of-band with another agent. The invite carries your identity and display name. If you pass a name, whoever redeems the invite is registered under it; without a name, the redeemer is registered under the name they announce when accepting. mode selects the invite kind: "one_time" (the default when omitted \u2014 consumed by the first redemption) or "public" (reusable, meant for open posting; every redeemer gets an independent channel; close it with revoke_invite \u2014 it has no expiry and is never consumed). A public invite cannot pre-assign a contact name, and does not survive a daemon restart (it must be re-generated and re-posted). Requires a bound identity.',{name:k.string().min(1).optional().describe('Optional name to register the peer who redeems this invite, e.g. "Bob". Omit to register them under their own name on acceptance. Not allowed with mode "public".'),mode:k.enum(["one_time","public"]).optional().describe('Invite kind. Omitted means "one_time" (single redemption, unchanged legacy behavior). "public" mints a reusable invite for open posting.')},async({name:r,mode:n},o)=>W(e(o),s=>s.generateInvite({name:r,mode:n}),s=>{let i=s.mode==="public"?`Reusable public invite created (invite_id ${s.inviteId}). Anyone holding the blob can redeem it, each as an independent contact, until you revoke_invite it. It will NOT survive a daemon restart \u2014 re-generate and re-post after one.`:r?`One-time invite for "${r}" created (invite_id ${s.inviteId}).`:`One-time invite created (invite_id ${s.inviteId}) \u2014 the contact will be registered under the name the recipient announces when accepting.`;return L(`${i} Share this blob out-of-band (they paste it into add_contact):
|
|
51
|
+
`,{mode:384,flag:"wx"}),await T$(n,t),await $$(t,384)}catch(o){try{await z$(n)}catch{}throw o}}var uo=class{stateDir;instanceId;path;constructor(e,r={}){if(typeof e=="string")this.stateDir=co(e),this.instanceId=null;else{if(!e||!$h.test(e.instanceId))throw new Error("Application identity instanceId must be a lowercase UUID.");this.stateDir=null,this.instanceId=e.instanceId}this.path=co(r.path??Sh(r.env))}rows(e){return this.instanceId===null?e.daemons:e.instances}key(){return this.instanceId??this.stateDir}async list(){let e=await Gu(this.path);return[...this.rows(e)[this.key()]?.identities??[]]}async has(e){return(await this.list()).includes(e)}async add(e){if(!e)throw new Error("Cannot add an empty identity name to ours-mcp.");let r=await Gu(this.path),n=this.rows(r),o=this.key(),s=n[o]?.identities??[];s.includes(e)||(n[o]={identities:[...s,e].sort()},await xh(this.path,r))}async remove(e){let r=await Gu(this.path),n=this.rows(r),o=this.key(),s=n[o];if(!s?.identities.includes(e))return;let i=s.identities.filter(a=>a!==e);i.length===0?delete n[o]:n[o]={identities:i},await xh(this.path,r)}};async function kh(t,e){let r=new Set(await t.list());return e.filter(n=>r.has(n.name))}Vt();import{attachOursClient as kD,OursError as TD,resolveDaemonConfig as zD}from"@ours.network/sdk";import{resolve as N$}from"node:path";var Th=["endpoint","expectedInstanceId","credentialPath"],A$=["port","stateDir","apiToken","apiVisibility"],j$=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;function Ht(t){return new Error(`Invalid external host profile: ${t}`)}function Bs(t){if(!t||typeof t!="object"||Array.isArray(t))throw Ht("expected a complete host profile object.");let e=t;if(Th.filter(c=>Object.hasOwn(e,c)).length!==Th.length)throw Ht("expected a complete host profile tuple: endpoint, expectedInstanceId, credentialPath.");let n=A$.filter(c=>Object.hasOwn(e,c));if(n.length)throw Ht(`legacy selection keys cannot be mixed with a host profile (${n.join(", ")}).`);let o=e.endpoint,s=e.expectedInstanceId,i=e.credentialPath;if(typeof o!="string"||o.trim()!==o||o==="")throw Ht("endpoint must be a non-empty HTTP or HTTPS origin.");if(typeof s!="string"||!j$.test(s))throw Ht("expectedInstanceId must be a lowercase UUID.");if(typeof i!="string"||i===""||!i.startsWith("/")||N$(i)!==i)throw Ht("credentialPath must be a normalized absolute path.");let a;try{a=new URL(o)}catch{throw Ht("endpoint must be an HTTP or HTTPS origin.")}if(a.protocol!=="http:"&&a.protocol!=="https:"||a.username||a.password||a.pathname!=="/"||a.search||a.hash)throw Ht("endpoint must be an HTTP or HTTPS origin without credentials, path, query, or fragment.");return{endpoint:a.origin,expectedInstanceId:s,credentialPath:i}}import{attachOursClient as FC}from"@ours.network/sdk";Xv();Dt();import{OursError as Lp}from"@ours.network/sdk";function L(t,e=!1){return{content:[{type:"text",text:t}],isError:e}}var Up=new WeakMap;function Qv(t,e){Up.set(t,e)}function Wo(t){return Up.get(t)??null}function $R(t){Up.delete(t)}async function SR(t){let e=Wo(t);if(!e)return!1;try{return await t.chooseIdentity({name:e,force:!1}),!0}catch{return $R(t),!1}}async function W(t,e,r){let n=await t,o;try{o=await e(n)}catch(s){if(s instanceof Lp&&s.code==="NOT_BOUND"&&await SR(n))try{return r(await e(n))}catch(i){if(i instanceof Lp)return L(i.message,!0);throw i}if(s instanceof Lp)return L(s.message,!0);throw s}return Wo(n)===null&&n.currentIdentity().then(s=>{Qv(n,s.name)}).catch(()=>{}),r(o)}var Fp=k.lazy(()=>k.union([k.null(),k.boolean(),k.number(),k.string(),k.array(Fp),k.record(Fp)]));function eb(t,e){t.tool("list_contact_commands","List the typed commands a contact currently advertises. The returned catalog is data; remote commands are not registered as MCP tools.",{contact:k.string().min(1).describe("Contact name or container id.")},async({contact:r},n)=>W(e(n),o=>o.listContactCommands({contact:r}),o=>{let s={contact:r,count:o.length,commands:o};return{content:[{type:"text",text:JSON.stringify(s,null,2)}],structuredContent:s,isError:!1}})),t.tool("send_command","Send a typed command to a contact after the SDK validates it against that contact's advertised schema. Use get_messages to retrieve a correlated command_result whose reply_to.wire_id matches request_wire_id.",{contact:k.string().min(1).describe("Contact name or container id."),command:k.string().min(1).describe("Advertised command name."),arguments:Fp.describe("Any JSON-compatible command arguments accepted by the advertised schema.")},async({contact:r,command:n,arguments:o},s)=>W(e(s),i=>i.sendCommand({contact:r,command:n,arguments:o}),i=>{let a={request_wire_id:i.wireId,outcome:i};return{content:[{type:"text",text:JSON.stringify(a,null,2)}],structuredContent:a,isError:i.kind==="refused"}}))}Dt();function kR(t){let e=new Map;for(let r of t)e.set(r.name,(e.get(r.name)??0)+1);return e}function tb(t){let e=kR(t);return t.map(r=>`\u2022 ${r.name} \u2014 ${r.container_id}${r.rootTag??""}${r.degradedQueued!==void 0?` \u2014 \u26A0 keys pending restore (${r.degradedQueued} queued)`:""}${(e.get(r.name)??0)>1?" \u2014 \u26A0 DUPLICATE NAME: sends to this name abort; address by container id, repair with rename_contact":""}${r.renamedFrom!==void 0?` \u2014 \u26A0 renamed on import (two contacts were named "${r.renamedFrom}"; do NOT assume the one keeping the bare name is the live one \u2014 verify by container id, settle with rename_contact)`:""}`)}function TR(t){if(!t)return"";let e=t.root_name||t.root_cid;return t.role_id?` [role "${t.role_id}" of ${e}]`:` [root identity of ${e}]`}function rb(t,e){t.tool("generate_invite",'Generate an invite to share out-of-band with another agent. The invite carries your identity and display name. If you pass a name, whoever redeems the invite is registered under it; without a name, the redeemer is registered under the name they announce when accepting. mode selects the invite kind: "one_time" (the default when omitted \u2014 consumed by the first redemption) or "public" (reusable, meant for open posting; every redeemer gets an independent channel; close it with revoke_invite \u2014 it has no expiry and is never consumed). A public invite cannot pre-assign a contact name, and does not survive a daemon restart (it must be re-generated and re-posted). Requires a bound identity.',{name:k.string().min(1).optional().describe('Optional name to register the peer who redeems this invite, e.g. "Bob". Omit to register them under their own name on acceptance. Not allowed with mode "public".'),mode:k.enum(["one_time","public"]).optional().describe('Invite kind. Omitted means "one_time" (single redemption, unchanged legacy behavior). "public" mints a reusable invite for open posting.')},async({name:r,mode:n},o)=>W(e(o),s=>s.generateInvite({name:r,mode:n}),s=>{let i=s.mode==="public"?`Reusable public invite created (invite_id ${s.inviteId}). Anyone holding the blob can redeem it, each as an independent contact, until you revoke_invite it. It will NOT survive a daemon restart \u2014 re-generate and re-post after one.`:r?`One-time invite for "${r}" created (invite_id ${s.inviteId}).`:`One-time invite created (invite_id ${s.inviteId}) \u2014 the contact will be registered under the name the recipient announces when accepting.`;return L(`${i} Share this blob out-of-band (they paste it into add_contact):
|
|
52
52
|
|
|
53
53
|
${s.blob}`)})),t.tool("list_invites","List the outstanding invites the bound identity has minted and not yet seen redeemed or revoked: invite_id, kind (one_time | public), assigned peer name if any, and creation time. Carries no key material. Use revoke_invite to close one \u2014 essential for public invites, which are never consumed.",{},async(r,n)=>W(e(n),o=>o.listInvites(),o=>{if(o.length===0)return L("No outstanding invites.");let s=o.map(i=>`\u2022 ${i.invite_id} \u2014 ${i.mode}${i.assigned?`, assigned name "${i.assigned}"`:""}${i.created?`, created ${i.created}`:""}`);return L(`Outstanding invites (${o.length}):
|
|
54
54
|
${s.join(`
|
|
@@ -78,5 +78,5 @@ Bio: ${a.bio}`:"",d=a.persona?`
|
|
|
78
78
|
Persona: ${a.persona}`:"";return L(`Bound to "${a.name}" (${a.cid})${c}.${u}${l}${d}`)}catch(a){if(a instanceof Vp)return L(a.message);throw a}}),t.tool("remove_identity","Permanently delete a persisted identity \u2014 its packet and all on-disk state. This cannot be undone.",{name:k.string().min(1).describe("Name of the identity to delete.")},async({name:o},s)=>{let i=await e(s);try{let a=await mb(r,o,()=>i.removeIdentity({name:o}));return a.kind==="temporary"&&a.close?L(`Removed temporary identity "${a.name}" and its state.${UR(a.close)}`):L(`Removed identity "${a.name}" and its state.`)}catch(a){if(a instanceof Vp&&a.code==="NO_SUCH_IDENTITY")return await r.remove(o),L(`Identity "${o}" was already absent; removed it from this ours-mcp application's identity list.`);if(a instanceof Vp)return L(a.message,!0);throw a}})}Dt();import{readFileSync as FR}from"node:fs";import{basename as VR,resolve as HR}from"node:path";import{errFileUnreadable as BR,OursError as Jp}from"@ours.network/sdk";function Xe(t,e,r=!1){let n="history_stored"in e&&e.history_stored===!1?`
|
|
79
79
|
|
|
80
80
|
WARNING: the item was not stored in this identity's local history. Delivery and local history are not transactional; there is no fallback or automatic retry.`:"";return{content:[{type:"text",text:`${t}${n}`}],structuredContent:{outcome:e},isError:r}}function gb(t,e,r={}){t.tool("send_message","Send an end-to-end-encrypted message to a known contact (by name or container id). If the recipient is not a contact yet, the connection is established automatically when possible: an intra-root sibling (a role under the same root) connects via its delegation cert, and an identity published in the host-local contact book connects via a registrar introduction \u2014 either way the message is delivered with the introduction, no invite needed. To reply to a specific message, pass reply_to_wire_id (from get_messages or list_history) and optionally reply_to_sentence (1-based index of the sentence you are answering). Requires a bound identity.",{contact:k.string().min(1).describe("Contact name or container id to send to."),text:k.string().min(1).describe("The message text."),reply_to_wire_id:k.string().optional().describe("wire_id (from get_messages or list_history) of the message this replies to."),reply_to_sentence:k.number().int().positive().optional().describe("Optional 1-based sentence index in the replied-to message.")},async({contact:n,text:o,reply_to_wire_id:s,reply_to_sentence:i},a)=>W(e(a),c=>c.sendMessage({contact:n,text:o,reply_to_wire_id:s,reply_to_sentence:i}),c=>{switch(c.kind){case"refused":return Xe(`Couldn't send to "${n}" (wire_id ${c.wireId}): their end-to-end encryption must be re-established after an upgrade before messages can go through. It was NOT sent and NOT downgraded to the old channel \u2014 the system re-offers the upgrade automatically; try again shortly.`,c,!0);case"migrating":return Xe(`Message queued for "${n}" (wire_id ${c.wireId}) \u2014 an encryption upgrade is completing; it will send automatically the moment the migration goes active (${c.queued} message${c.queued===1?"":"s"} queued).`,c);case"e2e":return c.notRetained?Xe(`Message sent to "${n}" over the end-to-end session (wire_id ${c.wireId}) \u2014 WARNING: the message body exceeds the redrive budget, so it is NOT retained for automatic resend. If the recipient loses its session, this message will NOT re-deliver automatically \u2014 confirm receipt or resend once the contact is confirmed back.`,c):Xe(`Message sent to "${n}" over the upgraded end-to-end session (wire_id ${c.wireId}).`,c);case"deferred":return Xe(`Message queued for "${n}" (wire_id ${c.wireId}) \u2014 the contact's encryption keys are being re-established after an upgrade (contact restore in progress); delivery is automatic once restored (${c.queued} message${c.queued===1?"":"s"} queued).`,c);case"introduced":return Xe(c.text,c);default:return Xe(`Message sent to "${n}" (wire_id ${c.wireId}).`,c)}})),t.tool("send_file","Send a file to a known contact (by name or container id). Provide EITHER `path` (the connector reads it as your OS user) OR `data_base64` + `filename` (inline bytes). Files and text are distinct messages \u2014 to caption a file, also send_message. Requires a bound identity.",{contact:k.string().min(1).describe("Contact name or container id to send to."),path:k.string().min(1).optional().describe("Filesystem path to the file to send (preferred). Read by the ours connector as YOUR OS user, then streamed to the daemon."),upload_id:k.string().min(1).optional().describe("Host-bridge staged upload identifier. Do not supply this directly."),data_base64:k.string().min(1).optional().describe("Inline file bytes, base64-encoded (alternative to path)."),filename:k.string().min(1).optional().describe("Filename to advertise (required with data_base64; defaults to basename of path)."),mime:k.string().optional().describe("MIME type (inferred from the path extension when omitted)."),reply_to_wire_id:k.string().optional().describe("wire_id (from unread or persistent-history tools) this file replies to."),reply_to_sentence:k.number().int().positive().optional().describe("Optional 1-based sentence index in the replied-to item.")},async({contact:n,path:o,upload_id:s,data_base64:i,filename:a,mime:c,reply_to_wire_id:u,reply_to_sentence:l},d)=>W(e(d),async f=>{if(+!!o+ +!!s+ +!!i!==1)throw new Jp("FILE_UNREADABLE","send_file requires exactly one of path, upload_id, or data_base64.");if(s){if(!r.networkHostFiles)throw new Jp("FILE_UNREADABLE","send_file upload_id is available only through the network host bridge.");return f.sendFile({contact:n,upload_id:s,filename:a,mime:c,reply_to_wire_id:u,reply_to_sentence:l})}if(!o)return f.sendFile({contact:n,data_base64:i,filename:a,mime:c,reply_to_wire_id:u,reply_to_sentence:l});if(r.networkHostFiles)throw new Jp("FILE_UNREADABLE","send_file path must be staged by the network host bridge.");let p=HR(o),h;try{h=FR(p)}catch(v){throw BR(String(v))}let g=await f.uploadFile(new Uint8Array(h),{filename:a??VR(p),mime:c});return f.sendFile({contact:n,upload_id:g.upload_id,filename:a,mime:c,reply_to_wire_id:u,reply_to_sentence:l})},f=>{let m=`File "${f.filename}" (${f.bytes} B${f.mime?`, ${f.mime}`:""})`;switch(f.kind){case"refused":return Xe(`Couldn't send ${m} to "${n}" (wire_id ${f.wireId}): their end-to-end encryption must be re-established after an upgrade first. It was NOT sent and NOT downgraded; the system re-offers the upgrade automatically \u2014 try again shortly.`,f,!0);case"migrating":return Xe(`${m} not sent to "${n}" yet \u2014 an encryption upgrade is completing; retry the file once the migration goes active (files aren't auto-queued like messages).`,f,!0);case"e2e":return f.notRetained?Xe(`${m} sent to "${n}" over the end-to-end session (wire_id ${f.wireId}) \u2014 WARNING: the file exceeds the 2 MiB redrive budget, so it is NOT retained for automatic resend. If the recipient loses its session (e.g. it was mid-restart), this file will NOT re-deliver automatically \u2014 confirm receipt or resend it once the contact is confirmed back.`,f):Xe(`${m} sent to "${n}" over the upgraded end-to-end session (wire_id ${f.wireId}).`,f);case"introduced":return Xe(f.text,f);default:return Xe(`${m} sent to "${n}" (wire_id ${f.wireId}).`,f)}})),t.tool("get_messages","Fetch the oldest unread messages for the bound identity and atomically mark that bounded batch read. Defaults to 50 and returns at most 200, plus the remaining unread count. Bodies remain available through persistent list_history/get_history_item. Read receipts are best-effort after the local read commit; there is no defer, outbox, fallback, or automatic retry.",{limit:k.number().int().min(1).max(200).optional().describe("Batch size from 1 to 200 (default 50).")},async({limit:n},o)=>W(e(o),s=>s.getMessages({limit:n}),s=>{let i={count:s.messages.length,messages:s.messages,command_results:s.command_results,commands_handled:s.commands_handled,remaining:s.remaining};return{content:[{type:"text",text:JSON.stringify(i,null,2)}],structuredContent:i,isError:!1}}))}Dt();function yb(t,e){t.tool("set_bio","Set the bound identity's profile bio (free text). For a role, the bio is embedded in the invites it generates. For the root identity, the refreshed profile is re-pinned into every role so future role invites carry the update.",{bio:k.string().describe("The new bio text (empty string clears it).")},async({bio:r},n)=>W(e(n),o=>o.setBio({bio:r}),o=>{let s=o.rolesRefreshed>0?` Root profile refreshed in ${o.rolesRefreshed} role(s).`:"";return L(`Updated the bio of "${o.identity}".${s}`)})),t.tool("advertise_migrate","Enable the e2e-migration capability (core.e2e.migrate) at runtime on the bound identity and proactively offer migration to every already-known eligible e2e contact. This is the staged-advertise trigger: an identity booted WITHOUT the migrate cap (so it forms a plain e2e session first) calls this to start the SAME migrations a default-cap boot would \u2014 closing the already-e2e-pair gap where a pinned pair with no inbound traffic would otherwise never migrate. Idempotent: re-enabling is a no-op for the cap, and the offer election stays fail-closed. Returns how many migration offers were initiated.",{},async(r,n)=>W(e(n),o=>o.advertiseMigrate(),({wasAdvertising:o,advertising:s,offers:i})=>L(`advertise_migrate: core.e2e.migrate ${s?"advertised":"NOT advertised"}${o?" (already advertising \u2014 cap unchanged)":""}; ${i} migration offer(s) initiated to eligible e2e contact(s).`))),t.tool("set_persona","Set the bound identity's local operating contract (persona, free text). The persona is how the agent behaves when it adopts this identity; it is NEVER shared via invites \u2014 only via the control-plane cluster registry. An agent must ask the user before adopting a persona. Empty string clears it.",{persona:k.string().describe("The new persona text (empty string clears it).")},async({persona:r},n)=>W(e(n),o=>o.setPersona({persona:r}),o=>L(`Updated the persona of "${o.identity}".`)))}function Gp(t,e,r,n={}){let o=new ta({name:"ours",version:e},{capabilities:{logging:{}}}),s=typeof t=="function"?t:()=>t;return n.networkHostFiles&&o.resource("application-identities","ours://application-identities",{mimeType:"application/json",description:"Application-visible identities for this daemon instance."},async i=>({contents:[{uri:i.href,mimeType:"application/json",text:JSON.stringify({identities:await r.list()})}]})),hb(o,s,r,n),rb(o,s),yb(o,s),gb(o,s,n),eb(o,s),cb(o,s,n),pb(o,s),o}function JR(t,e,r){let n;try{n=t()}catch(o){r(e,o);return}n&&typeof n.then=="function"&&n.then(void 0,o=>r(e,o))}function _b(t,e,r){JR(()=>t.sendLoggingMessage({level:"info",logger:"ours",data:e}),"sendLoggingMessage",r)}var vb=null,Wp=t=>{try{process.stderr.write(`ours: ${t}
|
|
81
|
-
`,e=>{e&&vb?.()})}catch{vb?.()}};var sa=class{constructor(e,r){this.client=e;this.server=r}stopped=!1;bound=null;abort=new AbortController;stop(){this.stopped=!0,this.abort.abort()}async run(){for(;!this.stopped;){if(this.bound===null){let r=Wo(this.client);if(r===null){await new Promise(n=>setTimeout(n,250));continue}this.bound=r,Wp(`[${r}] watching for arrivals`)}let e=this.bound;try{for await(let r of this.client.watchNotifications(e,{kinds:["inbound"],signal:this.abort.signal})){if(this.stopped)return;let n=r,o=n.event==="file_received"?`new file ${n.filename??"?"} from ${n.from??"?"}`:`new message from ${n.from??"?"}`;if(_b(this.server,o,(s,i)=>Wp(`[${e}] ${s} failed: ${String(i)}`)),Wo(this.client)!==e){this.bound=null;break}}}catch(r){if(this.stopped)return;Wp(`[${e}] arrival watch stopped (${String(r)}) \u2014 tool calls still work; retrying`),this.bound=null,await new Promise(n=>setTimeout(n,1e3))}}}};var KR="1.2.0-nightly.
|
|
81
|
+
`,e=>{e&&vb?.()})}catch{vb?.()}};var sa=class{constructor(e,r){this.client=e;this.server=r}stopped=!1;bound=null;abort=new AbortController;stop(){this.stopped=!0,this.abort.abort()}async run(){for(;!this.stopped;){if(this.bound===null){let r=Wo(this.client);if(r===null){await new Promise(n=>setTimeout(n,250));continue}this.bound=r,Wp(`[${r}] watching for arrivals`)}let e=this.bound;try{for await(let r of this.client.watchNotifications(e,{kinds:["inbound"],signal:this.abort.signal})){if(this.stopped)return;let n=r,o=n.event==="file_received"?`new file ${n.filename??"?"} from ${n.from??"?"}`:`new message from ${n.from??"?"}`;if(_b(this.server,o,(s,i)=>Wp(`[${e}] ${s} failed: ${String(i)}`)),Wo(this.client)!==e){this.bound=null;break}}}catch(r){if(this.stopped)return;Wp(`[${e}] arrival watch stopped (${String(r)}) \u2014 tool calls still work; retrying`),this.bound=null,await new Promise(n=>setTimeout(n,1e3))}}}};var KR="1.2.0-nightly.4";function FD(t){let e=Bs(t?.profile);if(typeof t?.applicationConfigPath!="string"||t.applicationConfigPath===""||!t.applicationConfigPath.startsWith("/")||GR(t.applicationConfigPath)!==t.applicationConfigPath)throw new Error("Network MCP applicationConfigPath must be a normalized absolute path.");let r=new uo({instanceId:e.expectedInstanceId},{path:t.applicationConfigPath}),n=new WeakMap,o=new Map,s=i=>{i.closed||!i.sessionId||!i.client||i.watcher||i.client.then(a=>{if(i.closed||i.watcher)return;let c=new sa(a,i.server);i.watcher=c,c.run()}).catch(a=>{process.stderr.write(`ours: network MCP notification attachment failed: ${String(a)}
|
|
82
82
|
`)})};return{createServer(i){let a,u=Gp(()=>{if(i.sessionMode()!=="external")throw new Error("Network MCP requires external session mode.");let l=i.leaseToken();if(!l)throw new Error("Network MCP requires an external owner.");return a.client||(a.client=WR({...e,sessionMode:"external",leaseToken:l,env:{}})),s(a),a.client},KR,r,{networkHostFiles:!0});return a={context:i,server:u,closed:!1},n.set(u,a),u},createTransport(i){return new Hs(i)},isInitializeRequest:eo,onSessionInitialized(i,a){let c=n.get(a);if(!c)throw new Error("Network MCP initialized an unknown server.");c.sessionId=i,o.set(i,c),s(c)},onSessionClosed(i){let a=o.get(i);a&&(o.delete(i),n.delete(a.server),a.closed=!0,a.watcher?.stop(),a.client?.then(c=>c.close()).catch(()=>{}))}}}export{FD as createNetworkMcpIntegration};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ours.network/mcp",
|
|
3
|
-
"version": "1.2.0-nightly.
|
|
3
|
+
"version": "1.2.0-nightly.4",
|
|
4
4
|
"description": "MCP adapter for the shared ours daemon, with application-local identity bookkeeping and secure agent-to-agent messaging tools over stdio.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "FSL-1.1-Apache-2.0",
|
|
@@ -51,8 +51,8 @@
|
|
|
51
51
|
"test:external-profile": "node test/native-profile-session.test.mjs && node test/external-profile-stdio-refresh.test.mjs"
|
|
52
52
|
},
|
|
53
53
|
"dependencies": {
|
|
54
|
-
"@ours.network/cli": "2.8.1-nightly.
|
|
55
|
-
"@ours.network/sdk": "3.8.1-nightly.
|
|
54
|
+
"@ours.network/cli": "2.8.1-nightly.2",
|
|
55
|
+
"@ours.network/sdk": "3.8.1-nightly.4"
|
|
56
56
|
},
|
|
57
57
|
"devDependencies": {
|
|
58
58
|
"@modelcontextprotocol/sdk": "^1.0.4",
|