onlymcp 0.17.0 → 0.20.0
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/LICENSE +33 -17
- package/README.md +2 -1
- package/dist/bin/cli.js +68 -583
- package/dist/bin/mcp.js +45 -73
- package/package.json +7 -10
- package/dist/apiBaseUrl.d.ts +0 -12
- package/dist/apiBaseUrl.js +0 -28
- package/dist/apiBaseUrl.js.map +0 -1
- package/dist/apiClient.d.ts +0 -296
- package/dist/apiClient.js +0 -224
- package/dist/apiClient.js.map +0 -1
- package/dist/auth/deviceLogin.d.ts +0 -5
- package/dist/auth/deviceLogin.js +0 -40
- package/dist/auth/deviceLogin.js.map +0 -1
- package/dist/auth/keyring.d.ts +0 -16
- package/dist/auth/keyring.js +0 -33
- package/dist/auth/keyring.js.map +0 -1
- package/dist/bin/cli.d.ts +0 -2
- package/dist/bin/cli.js.map +0 -1
- package/dist/bin/mcp.d.ts +0 -2
- package/dist/bin/mcp.js.map +0 -1
- package/dist/cache.d.ts +0 -7
- package/dist/cache.js +0 -32
- package/dist/cache.js.map +0 -1
- package/dist/deviceId.d.ts +0 -2
- package/dist/deviceId.js +0 -97
- package/dist/deviceId.js.map +0 -1
- package/dist/export/unpack.d.ts +0 -33
- package/dist/export/unpack.js +0 -54
- package/dist/export/unpack.js.map +0 -1
- package/dist/identity.d.ts +0 -29
- package/dist/identity.js +0 -116
- package/dist/identity.js.map +0 -1
- package/dist/import/collect.d.ts +0 -25
- package/dist/import/collect.js +0 -101
- package/dist/import/collect.js.map +0 -1
- package/dist/import/frontmatter.d.ts +0 -44
- package/dist/import/frontmatter.js +0 -93
- package/dist/import/frontmatter.js.map +0 -1
- package/dist/import/plan.d.ts +0 -74
- package/dist/import/plan.js +0 -190
- package/dist/import/plan.js.map +0 -1
- package/dist/import/prune.d.ts +0 -46
- package/dist/import/prune.js +0 -61
- package/dist/import/prune.js.map +0 -1
- package/dist/import/secrets.d.ts +0 -7
- package/dist/import/secrets.js +0 -77
- package/dist/import/secrets.js.map +0 -1
- package/dist/import/upload.d.ts +0 -21
- package/dist/import/upload.js +0 -99
- package/dist/import/upload.js.map +0 -1
- package/dist/install.d.ts +0 -81
- package/dist/install.js +0 -168
- package/dist/install.js.map +0 -1
- package/dist/instructions.d.ts +0 -4
- package/dist/instructions.js +0 -67
- package/dist/instructions.js.map +0 -1
- package/dist/memoryPath.d.ts +0 -1
- package/dist/memoryPath.js +0 -13
- package/dist/memoryPath.js.map +0 -1
- package/dist/memorySync.d.ts +0 -28
- package/dist/memorySync.js +0 -56
- package/dist/memorySync.js.map +0 -1
- package/dist/paths.d.ts +0 -18
- package/dist/paths.js +0 -62
- package/dist/paths.js.map +0 -1
- package/dist/registry/caveats.d.ts +0 -17
- package/dist/registry/caveats.js +0 -74
- package/dist/registry/caveats.js.map +0 -1
- package/dist/registry/clients.d.ts +0 -17
- package/dist/registry/clients.js +0 -402
- package/dist/registry/clients.js.map +0 -1
- package/dist/registry/index.d.ts +0 -6
- package/dist/registry/index.js +0 -7
- package/dist/registry/index.js.map +0 -1
- package/dist/registry/serverInfo.d.ts +0 -25
- package/dist/registry/serverInfo.js +0 -33
- package/dist/registry/serverInfo.js.map +0 -1
- package/dist/registry/servers.d.ts +0 -58
- package/dist/registry/servers.js +0 -259
- package/dist/registry/servers.js.map +0 -1
- package/dist/registry/toolHints.d.ts +0 -29
- package/dist/registry/toolHints.js +0 -41
- package/dist/registry/toolHints.js.map +0 -1
- package/dist/registry/types.d.ts +0 -71
- package/dist/registry/types.js +0 -6
- package/dist/registry/types.js.map +0 -1
- package/dist/skillFilePath.d.ts +0 -1
- package/dist/skillFilePath.js +0 -29
- package/dist/skillFilePath.js.map +0 -1
- package/dist/stubIgnore.d.ts +0 -22
- package/dist/stubIgnore.js +0 -29
- package/dist/stubIgnore.js.map +0 -1
- package/dist/stubs.d.ts +0 -12
- package/dist/stubs.js +0 -188
- package/dist/stubs.js.map +0 -1
- package/dist/tools/connections.d.ts +0 -154
- package/dist/tools/connections.js +0 -164
- package/dist/tools/connections.js.map +0 -1
- package/dist/tools/getAgentDefinition.d.ts +0 -26
- package/dist/tools/getAgentDefinition.js +0 -29
- package/dist/tools/getAgentDefinition.js.map +0 -1
- package/dist/tools/getSkill.d.ts +0 -26
- package/dist/tools/getSkill.js +0 -26
- package/dist/tools/getSkill.js.map +0 -1
- package/dist/tools/getSkillFile.d.ts +0 -27
- package/dist/tools/getSkillFile.js +0 -39
- package/dist/tools/getSkillFile.js.map +0 -1
- package/dist/tools/index.d.ts +0 -263
- package/dist/tools/index.js +0 -69
- package/dist/tools/index.js.map +0 -1
- package/dist/tools/lists.d.ts +0 -38
- package/dist/tools/lists.js +0 -39
- package/dist/tools/lists.js.map +0 -1
- package/dist/tools/memoryGraph.d.ts +0 -69
- package/dist/tools/memoryGraph.js +0 -128
- package/dist/tools/memoryGraph.js.map +0 -1
- package/dist/tools/memoryRead.d.ts +0 -25
- package/dist/tools/memoryRead.js +0 -33
- package/dist/tools/memoryRead.js.map +0 -1
- package/dist/tools/memoryWrite.d.ts +0 -27
- package/dist/tools/memoryWrite.js +0 -34
- package/dist/tools/memoryWrite.js.map +0 -1
- package/dist/tools/write.d.ts +0 -166
- package/dist/tools/write.js +0 -193
- package/dist/tools/write.js.map +0 -1
package/dist/bin/mcp.js
CHANGED
|
@@ -1,74 +1,46 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
serverInfo(baseUrl, version), { capabilities: { tools: {} }, instructions: catalog });
|
|
48
|
-
server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: listedTools(tools) }));
|
|
49
|
-
server.setRequestHandler(CallToolRequestSchema, async (req) => {
|
|
50
|
-
const tool = tools.find((t) => t.name === req.params.name);
|
|
51
|
-
if (!tool)
|
|
52
|
-
return { content: [{ type: 'text', text: 'errors.UNKNOWN_TOOL' }], isError: true };
|
|
53
|
-
const parsed = tool.inputSchema.safeParse(req.params.arguments ?? {});
|
|
54
|
-
if (!parsed.success) {
|
|
55
|
-
return { content: [{ type: 'text', text: 'errors.INVALID_ARGUMENTS' }], isError: true };
|
|
56
|
-
}
|
|
57
|
-
return tool.handler(parsed.data);
|
|
58
|
-
});
|
|
59
|
-
// Stubs beim Start auffrischen, fuer jeden Client mit eigenem Scanner. Faellt
|
|
60
|
-
// das aus (offline, nicht angemeldet), laeuft der Server trotzdem an: die
|
|
61
|
-
// vorhandenen Stubs bleiben gueltig, und der eigentliche Fehler zeigt sich
|
|
62
|
-
// erst beim Werkzeugaufruf mit klarem Code. Ein Client ohne Scanner bekommt
|
|
63
|
-
// hier gar nichts und braucht auch nichts: fuer ihn traegt `catalog`.
|
|
64
|
-
//
|
|
65
|
-
// stub-ignore first. A bridge that cannot read it writes no stub at all,
|
|
66
|
-
// rather than every stub the file is there to keep out.
|
|
67
|
-
readStubIgnore()
|
|
68
|
-
.then((ignore) => {
|
|
69
|
-
for (const dir of stubDirs())
|
|
70
|
-
writeStubs(api, dir, { ignore }).catch(() => { });
|
|
71
|
-
})
|
|
72
|
-
.catch(() => { });
|
|
73
|
-
await server.connect(new StdioServerTransport());
|
|
74
|
-
//# sourceMappingURL=mcp.js.map
|
|
2
|
+
import{Server as xn}from"@modelcontextprotocol/sdk/server/index.js";import{StdioServerTransport as Sn}from"@modelcontextprotocol/sdk/server/stdio.js";import{CallToolRequestSchema as wn,ListToolsRequestSchema as kn}from"@modelcontextprotocol/sdk/types.js";import{hostname as _t}from"node:os";import{execFile as xt}from"node:child_process";import{hostname as St}from"node:os";import{readFile as wt}from"node:fs/promises";import{promisify as kt}from"node:util";import{randomUUID as pe}from"node:crypto";import{link as dt,mkdir as pt,readFile as mt,rename as ut,rm as ht,writeFile as me}from"node:fs/promises";import{basename as gt,dirname as he,join as ft}from"node:path";import{existsSync as ct}from"node:fs";import{homedir as se}from"node:os";import{join as C}from"node:path";function E(){return process.env.ONLYMCP_HOME??C(se(),".claude","onlymcp")}function ie(){return process.env.ONLYMCP_HOME??se()}function ae(){return C(E(),"device-id")}function le(){return C(E(),"cache")}function ce(){return C(E(),"stub-ignore")}function de(){let t=[];process.env.CLAUDE_PLUGIN_ROOT&&t.push(process.env.CLAUDE_PLUGIN_ROOT);for(let e of(process.env.ONLYMCP_STUB_DIRS??"").split(":"))e&&t.push(e);for(let e of[C(ie(),".claude"),C(ie(),".codex")])ct(e)&&!t.includes(e)&&t.push(e);return t.length>0?t:[C(E(),"plugin")]}var yt=/^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/,ue;function ge(){return ue??=bt(),ue}async function B(t){try{let e=(await mt(t,"utf8")).trim().toLowerCase();return yt.test(e)?e:null}catch{return null}}async function bt(){let t=ae(),e=await B(t);if(e)return e;try{return await pt(he(t),{recursive:!0}),await Ct(t)}catch{return null}}var vt=new Set(["EPERM","ENOTSUP","EOPNOTSUPP","ENOSYS","EXDEV"]);async function Ct(t){let e=pe(),n=ft(he(t),`.${gt(t)}.${process.pid}.${pe()}.tmp`);try{await me(n,`${e}
|
|
3
|
+
`,{flag:"wx",mode:384});try{return await dt(n,t),e}catch(r){let i=r.code;if(i!=="EEXIST"&&!vt.has(i??""))throw r;if(i!=="EEXIST")try{return await me(t,`${e}
|
|
4
|
+
`,{flag:"wx",mode:384}),e}catch(d){if(d.code!=="EEXIST")throw d}}let o=await B(t);return o||(await ut(n,t),await B(t)??e)}finally{await ht(n,{force:!0}).catch(()=>{})}}var M="0.20.0";var At=kt(xt),Tt=`onlymcp-cli/${M} (${process.platform} ${process.arch}; node ${process.versions.node})`,fe=200;async function ye(t,e){let n;try{return await Promise.race([t,new Promise(o=>{n=setTimeout(()=>o(null),e),n.unref?.()})])}catch{return null}finally{n&&clearTimeout(n)}}async function $t(){try{if(process.platform==="linux"){let t=wt("/sys/class/dmi/id/product_version","utf8"),n=(await ye(t,fe))?.trim();return!n||/^(to be filled|default string|system version|none|n\/a)/i.test(n)?null:n}if(process.platform==="darwin"){let t=At("sysctl",["-n","hw.model"]);return(await ye(t,fe))?.stdout.trim()||null}}catch{}return null}async function It(){let t="unknown";try{t=St()||"unknown"}catch{}let e=await $t();return(e&&e!==t?`${t} (${e})`:t).slice(0,60)}var be=null;async function V(){be??=await It();let t=await ge();return{"user-agent":Tt,"x-onlymcp-device":be,...t?{"x-onlymcp-device-id":t}:{}}}var a=class extends Error{constructor(n,o={},r=0){super(n);this.code=n;this.params=o;this.status=r;this.name="ApiError"}code;params;status},P=class{constructor(e,n){this.baseUrl=e;this.token=n}baseUrl;token;async call(e,n={}){let o=this.token();if(!o)throw new a("errors.NOT_LOGGED_IN");let r=await fetch(`${this.baseUrl}${e}`,{...n,headers:{...await V(),...n.headers??{},authorization:`Bearer ${o}`,"content-type":"application/json"}});if(r.status===204)return;let i=await r.json().catch(()=>({}));if(!r.ok)throw new a(i.code??"errors.UNKNOWN",i.params??{},r.status);return i}getMe(){return this.call("/api/me")}reportRun(e,n){return this.call("/api/devices/current/run",{method:"POST",body:JSON.stringify({kind:e,files:n}),signal:AbortSignal.timeout(5e3)})}signOut(){return this.call("/api/auth/sign-out",{method:"POST",body:"{}",signal:AbortSignal.timeout(5e3)})}listSkills(){return this.call("/api/skills")}getSkill(e){return this.call(`/api/skills/${encodeURIComponent(e)}`)}putSkill(e,n,o={}){return this.call(`/api/skills/${encodeURIComponent(e)}`,{method:"PUT",body:JSON.stringify({body:n,...o})})}skillFileUrl(e,n){let o=n.split("/").map(encodeURIComponent).join("/");return`/api/skills/${encodeURIComponent(e)}/files/${o}`}getSkillFile(e,n){return this.call(this.skillFileUrl(e,n))}putSkillFile(e,n,o,r="utf8"){return this.call(this.skillFileUrl(e,n),{method:"PUT",body:JSON.stringify({content:o,encoding:r})})}listAgents(){return this.call("/api/agents")}putAgent(e,n){return this.call(`/api/agents/${encodeURIComponent(e)}`,{method:"PUT",body:JSON.stringify(n)})}getAgent(e,{use:n=!1}={}){return this.call(`/api/agents/${encodeURIComponent(e)}${n?"?use=1":""}`)}readMemory(e){return this.call(this.memoryUrl(e))}writeMemory(e,n,o){return this.call(this.memoryUrl(e),{method:"PUT",body:JSON.stringify({content:n,deviceLabel:o})})}memoryUrl(e){return`/api/memory/${e.split("/").map(encodeURIComponent).join("/")}`}listMemory(){return this.call("/api/memory")}searchContent(e,n={}){let o=new URLSearchParams({q:e});return n.types?.length&&o.set("types",n.types.join(",")),n.limit&&o.set("limit",String(n.limit)),this.call(`/api/search?${o.toString()}`)}memoryTree(e="all"){return this.call(`/api/memory/tree?scope=${encodeURIComponent(e)}`)}moveMemory(e,n,o=!0,r=_t()){return this.call("/api/memory/move",{method:"POST",body:JSON.stringify({from:e,to:n,updateLinks:o,deviceLabel:r})})}async exportArchive(e={}){let n=this.token();if(!n)throw new a("errors.NOT_LOGGED_IN");let o=new URLSearchParams;e.scope&&o.set("scope",e.scope),e.types?.length&&o.set("types",e.types.join(","));let r=o.size>0?`?${o.toString()}`:"",i=await fetch(`${this.baseUrl}/api/export${r}`,{headers:{...await V(),authorization:`Bearer ${n}`}});if(!i.ok){let d=await i.json().catch(()=>({}));throw new a(d.code??"errors.UNKNOWN",d.params??{},i.status)}return i}deleteMemory(e){return this.call(this.memoryUrl(e),{method:"DELETE"})}deleteSkill(e){return this.call(`/api/skills/${encodeURIComponent(e)}`,{method:"DELETE"})}deleteSkillFile(e,n){return this.call(this.skillFileUrl(e,n),{method:"DELETE"})}deleteAgent(e){return this.call(`/api/agents/${encodeURIComponent(e)}`,{method:"DELETE"})}listConnections(){return this.call("/api/mcp-connections")}createConnection(e){return this.call("/api/mcp-connections",{method:"POST",body:JSON.stringify(e)})}updateConnection(e,n){return this.call(`/api/mcp-connections/${e}`,{method:"PATCH",body:JSON.stringify(n)})}deleteConnection(e){return this.call(`/api/mcp-connections/${e}`,{method:"DELETE"})}listCapabilities(e){return this.call(`/api/mcp-connections/${e}/capabilities`)}toggleCapability(e,n,o){return this.call(`/api/mcp-connections/${e}/capabilities/${n}`,{method:"PATCH",body:JSON.stringify({enabled:o})})}};var Ot="https://only-mcp.com";function ve(t=process.env.ONLYMCP_API_URL){if(t===void 0)return Ot;let e;try{e=new URL(t).protocol}catch{}if(e!=="http:"&&e!=="https:"){let n=t.replace(/\/\/[^/@]*@/,"//***@");throw new Error(`ONLYMCP_API_URL is not a valid http(s) URL: ${JSON.stringify(n)}`)}return t}import{Entry as Nt}from"@napi-rs/keyring";function Lt(t,e){let n=()=>new Nt(t,e);return{save(o){n().setPassword(o)},read(){try{return n().getPassword()}catch{return null}},clear(){try{n().deletePassword()}catch{}}}}var Ce=Lt("onlymcp","session-token");import U from"cacache";var Et=Number(process.env.ONLYMCP_TTL_SECONDS??360*60),R=class{constructor(e=le()){this.dir=e}dir;async get(e){try{let n=await U.get(this.dir,e),o=n.metadata;return!o||o.expiresAt<=Date.now()?(await U.rm.entry(this.dir,e),null):n.data.toString("utf8")}catch{return null}}async set(e,n,o=Et){await U.put(this.dir,e,n,{metadata:{expiresAt:Date.now()+o*1e3}})}async clear(){await U.rm.all(this.dir)}};var xe=["OnlyMCP holds this user's skills, agents and memory in the cloud, identical","on every machine. The names below are names only, not content: call","get_skill(name) to load a skill before following it, and","get_agent_definition(name) for an agent. Call list_skills or list_agents for","anything not named here. Memory is live: memory_read(path) and","memory_write(path, content). All of it is writable, not just readable:","skill_write, agent_write and the matching *_delete tools; connection_create","adds another MCP server to this account.","Link with [[name]] or typed: [[skill:name]], [[agent:name]], [[mcp:slug]], [[memory:path]]."].join(" "),Mt=["Memory is a vault, not a scratch file: read MEMORY.md first, it is the index.","After finishing a task, write one solutions/sol-*.md for what was not obvious","and one entry in history/YYYY-MM-DD.md. Link related files with [[name]];","memory_links(path) says which of a file's links point nowhere yet."].join(" ");function Se(t,e,n,o){if(n.length===0)return"";let r=[];for(let u of n){let g=n.length-r.length-1,f=g>0?` (+${g} more, call ${e})`:"",A=`
|
|
5
|
+
|
|
6
|
+
${t}: ${[...r,u].join(", ")}${f}`;if(o+A.length>1800)break;r.push(u)}if(r.length===0)return`
|
|
7
|
+
|
|
8
|
+
${t}: call ${e}`;let i=n.length-r.length,d=i>0?` (+${i} more, call ${e})`:"";return`
|
|
9
|
+
|
|
10
|
+
${t}: ${r.join(", ")}${d}`}function K(t,e,n={}){let o=n.brainvault===!1?xe:`${xe} ${Mt}`,r=e.length>0?26:0;return o+=Se("Skills","list_skills",t,o.length+r),o+=Se("Agents","list_agents",e,o.length),o}function J(t,e){let n=new URL(t);if(n.protocol!=="http:"&&n.protocol!=="https:")throw new TypeError(`serverInfo: "${t}" is not an http(s) origin`);let o=n.origin;return{name:"onlymcp",title:"OnlyMCP",version:e,websiteUrl:o,icons:[{src:`${o}/brand/connector-512.png`,mimeType:"image/png"},{src:`${o}/brand/favicon.svg`,mimeType:"image/svg+xml"}]}}import{access as zt,mkdir as X,readFile as jt,rm as Ae,writeFile as D}from"node:fs/promises";import{dirname as Gt,join as _}from"node:path";function we(t){if(!t.startsWith(`---
|
|
11
|
+
`))return null;let e=t.indexOf(`
|
|
12
|
+
---`,3);return e<0?null:t.slice(4,e)}function q(t,e){if(!/^[a-zA-Z0-9_-]+$/.test(e))return;let n=new RegExp(`^${e}:[ \\t]*(.*)$`,"m").exec(t);if(!n)return;let r=n[1].trim().replace(/^(['"])(.*)\1$/,"$2").trim();return r.length>0?r:void 0}import{readFile as Pt}from"node:fs/promises";var Y=()=>!1;function Ut(t){return t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function Rt(t){let e=t.split(/\r?\n/).map(n=>n.trim()).filter(n=>n!==""&&!n.startsWith("#")).map(n=>new RegExp(`^${n.split("*").map(Ut).join(".*")}$`));return n=>e.some(o=>o.test(n))}async function ke(t=ce()){try{return Rt(await Pt(t,"utf8"))}catch(e){if(e.code==="ENOENT")return Y;throw e}}var Dt=/^[A-Za-z0-9][A-Za-z0-9._-]*$/;function I(t){if(t.length===0||t.length>200||t==="SKILL.md")return!1;let e=t.split("/");return e.length>8?!1:e.every(n=>Dt.test(n)&&n!==".."&&n!==".")}var Ft=/^[a-z0-9]+(-[a-z0-9]+)*$/,Ht=/^[a-z0-9]+(-[a-z0-9]+)*(:[a-z0-9]+(-[a-z0-9]+)*)?$/,Z="x-onlymcp-stub";function z(t){return t.replace(/:/g,"-")}function j(t){return(t??"").replace(/[\r\n]+/g," ").trim()}async function Q(t,e){let n;try{n=await jt(t,"utf8")}catch{return!0}let o=we(n);if(o===null||q(o,Z)!=="true")return!1;let r=q(o,"x-onlymcp-name");return r===void 0||r===e}async function Te(t,e){return await zt(t).then(()=>!0,()=>!1)&&await Q(t,e)}async function $e(t,e,n={}){let o=n.ignore??Y,[{skills:r},{agents:i}]=await Promise.all([t.listSkills(),t.listAgents()]),d=0,u=0,g=[],f=[],A=0;for(let s of r){if(!Ht.test(s.name))continue;let b=_(e,"skills",z(s.name)),T=_(b,"SKILL.md");if(o(s.name)||o(z(s.name))){f.push(s.name),await Te(T,s.name)&&(await Ae(b,{recursive:!0,force:!0}),A+=1);continue}if(!await Q(T,s.name)){g.push(`skills/${z(s.name)}`);continue}await X(b,{recursive:!0}),await D(T,`---
|
|
13
|
+
name: ${z(s.name)}
|
|
14
|
+
description: ${j(s.description)||"Synchronisiert ueber OnlyMCP. Inhalt wird bei Bedarf geladen."}
|
|
15
|
+
${Z}: true
|
|
16
|
+
x-onlymcp-name: ${s.name}
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
Call \`get_skill({ name: "${s.name}" })\` on the OnlyMCP server and follow whatever comes back.
|
|
20
|
+
`,"utf8"),u+=1;try{let L=await t.getSkill(s.name);for(let $ of L.files??[]){if(!I($.path))continue;let H=await t.getSkillFile(s.name,$.path),W=_(b,...$.path.split("/"));await X(Gt(W),{recursive:!0}),H.encoding==="base64"?await D(W,Buffer.from(H.content,"base64")):await D(W,H.content,"utf8"),d+=1}}catch{}}await X(_(e,"agents"),{recursive:!0});let re=0;for(let s of i){if(!Ft.test(s.name))continue;let b=_(e,"agents",`${s.name}.md`);if(o(s.name)){f.push(s.name),await Te(b,s.name)&&(await Ae(b),A+=1);continue}if(!await Q(b,s.name)){g.push(`agents/${s.name}.md`);continue}let T=j(s.description),L=s.model?j(s.model):"",$=s.tools.map(j).join(", ");await D(b,`---
|
|
21
|
+
name: ${s.name}
|
|
22
|
+
description: ${T}
|
|
23
|
+
${L?`model: ${L}
|
|
24
|
+
`:""}tools: ${$}
|
|
25
|
+
${Z}: true
|
|
26
|
+
x-onlymcp-name: ${s.name}
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
Call \`get_agent_definition({ name: "${s.name}" })\` on the OnlyMCP server and follow whatever comes back.
|
|
30
|
+
`,"utf8"),re+=1}return{skills:u,agents:re,files:d,kept:g,ignored:f,removed:A}}import{z as Cn}from"zod";var p=t=>({title:t,annotations:{readOnlyHint:!0,openWorldHint:!1}}),m=(t,e)=>({title:t,annotations:{readOnlyHint:!1,destructiveHint:e.destructive,idempotentHint:e.idempotent,openWorldHint:e.openWorld??!1}}),ee={list_memory:p("List memory files"),memory_read:p("Read a memory file"),memory_write:m("Write a memory file",{destructive:!0,idempotent:!0}),memory_delete:m("Delete a memory file",{destructive:!0,idempotent:!1}),memory_search:p("Search memory"),memory_tree:p("Show the memory tree"),memory_move:m("Move a memory file or folder",{destructive:!1,idempotent:!1}),memory_links:p("Show memory links"),list_skills:p("List skills"),get_skill:p("Load a skill"),skill_write:m("Write a skill",{destructive:!0,idempotent:!0}),skill_delete:m("Delete a skill",{destructive:!0,idempotent:!1}),list_skill_files:p("List skill files"),get_skill_file:p("Read a skill file"),skill_file_write:m("Write a skill file",{destructive:!0,idempotent:!0}),skill_file_delete:m("Delete a skill file",{destructive:!0,idempotent:!1}),list_agents:p("List agents"),get_agent_definition:p("Load an agent definition"),agent_write:m("Write an agent",{destructive:!0,idempotent:!0}),agent_delete:m("Delete an agent",{destructive:!0,idempotent:!1}),list_connections:p("List connections"),connection_create:m("Add a connection",{destructive:!1,idempotent:!1,openWorld:!0}),connection_update:m("Update a connection",{destructive:!1,idempotent:!0}),connection_delete:m("Delete a connection",{destructive:!0,idempotent:!1}),connection_tools:p("List a connection's tools"),connection_tool_toggle:m("Switch a connection tool on or off",{destructive:!1,idempotent:!0}),connection_tool_schema:p("Show a connection tool's schema"),connection_call:m("Call a connection tool",{destructive:!0,idempotent:!1,openWorld:!0})};import{z as Ie}from"zod";var Wt=Ie.object({name:Ie.string().min(1).max(64)});function _e(t,e){return{name:"get_agent_definition",description:"Delivers an agent's system prompt from the OnlyMCP cloud.",inputSchema:Wt,async handler(n){let o=`agent:${n.name}`,r=await e.get(o);if(r!==null)return{content:[{type:"text",text:r}]};try{let i=await t.getAgent(n.name,{use:!0});return await e.set(o,i.body),{content:[{type:"text",text:i.body}]}}catch(i){return{content:[{type:"text",text:i instanceof a?i.code:"errors.UNKNOWN"}],isError:!0}}}}}import{z as te}from"zod";var Bt=te.object({name:te.string().min(1).max(64),path:te.string().min(1).max(200)});function Oe(t){return{name:"get_skill_file",description:"Delivers a single companion file of a skill from the OnlyMCP cloud, e.g. references/palette.md. Usually not needed: `npx onlymcp sync` places these files next to the SKILL.md.",inputSchema:Bt,async handler(e){try{let n=await t.getSkillFile(e.name,e.path);return n.encoding==="base64"?{content:[{type:"text",text:`errors.BINARY_FILE ${n.path} (${n.size} bytes) - fetch it to disk with \`npx onlymcp sync\`.`}],isError:!0}:{content:[{type:"text",text:n.content}]}}catch(n){return{content:[{type:"text",text:n instanceof a?n.code:"errors.UNKNOWN"}],isError:!0}}}}}import{z as Ne}from"zod";var Vt=Ne.object({name:Ne.string().min(1).max(64)});function Le(t,e){return{name:"get_skill",description:"Delivers a skill's full content from the OnlyMCP cloud. Called from the stub files.",inputSchema:Vt,async handler(n){let o=`skill:${n.name}`,r=await e.get(o);if(r!==null)return{content:[{type:"text",text:r}]};try{let i=await t.getSkill(n.name);return await e.set(o,i.body),{content:[{type:"text",text:i.body}]}}catch(i){return{content:[{type:"text",text:i instanceof a?i.code:"errors.UNKNOWN"}],isError:!0}}}}}import{z as Kt}from"zod";var Ee=Kt.object({});function Me(t){return{name:"list_skills",description:"List every skill name available to this user. Use when a skill you need is not named in the server instructions.",inputSchema:Ee,async handler(){try{let{skills:e}=await t.listSkills();return{content:[{type:"text",text:e.map(n=>n.name).join(`
|
|
31
|
+
`)}]}}catch(e){return{content:[{type:"text",text:e instanceof a?e.code:"errors.UNKNOWN"}],isError:!0}}}}}function Pe(t){return{name:"list_agents",description:"List every agent available to this user, with its description. Use when this client has no agent files of its own.",inputSchema:Ee,async handler(){try{let{agents:e}=await t.listAgents();return{content:[{type:"text",text:e.map(o=>`${o.name}: ${o.description}`).join(`
|
|
32
|
+
`)}]}}catch(e){return{content:[{type:"text",text:e instanceof a?e.code:"errors.UNKNOWN"}],isError:!0}}}}}import{z as Ue}from"zod";var Jt=/^[a-z0-9][a-z0-9._-]*(\/[a-z0-9][a-z0-9._-]*)*\.md$/i;function y(t){return Jt.test(t)&&!t.split("/").includes("..")}var qt=Ue.object({path:Ue.string().min(3).max(256)});function Re(t){let e=new Map;return{name:"memory_read",description:"Reads a memory file live from the OnlyMCP cloud. No disk cache.",inputSchema:qt,async handler(n){if(!y(n.path))return{content:[{type:"text",text:"errors.INVALID_PATH"}],isError:!0};try{let o=e.get(n.path);return o||(o=t.readMemory(n.path).then(r=>r.content),e.set(n.path,o),o.finally(()=>e.delete(n.path))),{content:[{type:"text",text:await o}]}}catch(o){return{content:[{type:"text",text:o instanceof a?o.code:"errors.UNKNOWN"}],isError:!0}}}}}import{hostname as Yt}from"node:os";import{z as ne}from"zod";var Xt=ne.object({path:ne.string().min(3).max(256),content:ne.string().max(1e6)});function De(t){return{name:"memory_write",description:"Writes a memory file live into the OnlyMCP cloud (write-through).",inputSchema:Xt,async handler(e){if(!y(e.path))return{content:[{type:"text",text:"errors.INVALID_PATH"}],isError:!0};try{let n=await t.writeMemory(e.path,e.content,Yt()),o=n.warning?`${n.path} ${n.updatedAt} ${n.warning.code} ${JSON.stringify(n.warning.params)}`:`${n.path} ${n.updatedAt}`;return n.routedTo&&(o+=` (created in team ${n.routedTo.teamName})`),{content:[{type:"text",text:o}]}}catch(n){return{content:[{type:"text",text:n instanceof a?n.code:"errors.UNKNOWN"}],isError:!0}}}}}import{z as h}from"zod";var x=t=>({content:[{type:"text",text:t}]}),w=t=>({content:[{type:"text",text:t}],isError:!0});function G(t){return t instanceof a?t.code:"errors.UNKNOWN"}var Zt=h.object({query:h.string().min(1).max(200),types:h.string().max(64).optional(),limit:h.number().int().min(1).max(50).optional()});function je(t){return{name:"memory_search",description:"Full-text search across memory, skills and agents. Delivers the best hits with a short snippet each.",inputSchema:Zt,async handler(e){try{let{hits:n}=await t.searchContent(e.query,{types:e.types?.split(",").map(o=>o.trim()).filter(o=>o!==""),limit:e.limit});return n.length===0?x(`Nothing found for ${e.query}`):x(n.map(o=>`${o.kind} ${o.path??o.name}${o.scope==="team"?" (team)":""}
|
|
33
|
+
${o.snippet}`).join(`
|
|
34
|
+
`))}catch(n){return w(G(n))}}}}var Qt=h.object({scope:h.string().max(96).optional()});function Ge(t){return{name:"memory_tree",description:"This account's folder structure: every folder, empty ones included, and the files in it.",inputSchema:Qt,async handler(e){try{let{nodes:n}=await t.memoryTree(e.scope??"all");return n.length===0?x("(empty)"):x(n.map(o=>{let r=o.path.split("/").length-1,i=o.kind==="folder"?`${o.name}/`:o.name;return`${" ".repeat(r)}${i}${o.scope==="team"?" (team)":""}`}).join(`
|
|
35
|
+
`))}catch(n){return w(G(n))}}}}var en=h.object({from:h.string().min(3).max(256),to:h.string().min(3).max(256),updateLinks:h.boolean().optional()});function ze(t){return`${t} ${t===1?"file":"files"}`}function Fe(t){return{name:"memory_move",description:"Moves or renames a memory file. Every [[link]] that would no longer find it follows along, by name or by path, unless turned off.",inputSchema:en,async handler(e){if(!y(e.from)||!y(e.to))return w("errors.INVALID_PATH");let n=e.updateLinks??!0;try{let o=await t.moveMemory(e.from,e.to,n);return x(`${o.from} moved to ${o.to}`+(n?`, links updated in ${ze(o.rewritten)}, ${ze(o.skipped)} left unchanged`:""))}catch(o){return w(G(o))}}}}var tn=h.object({path:h.string().min(3).max(256)});function He(t){return{name:"memory_links",description:"A memory file's [[links]], split between the ones that point somewhere and the ones that point nowhere.",inputSchema:tn,async handler(e){if(!y(e.path))return w("errors.INVALID_PATH");try{let n=await t.readMemory(e.path),{resolved:o,unresolved:r}=n.links;return o.length===0&&r.length===0?x(`${e.path} does not link to anything.`):x([o.length>0?`Resolved: ${o.join(", ")}`:"",r.length>0?`Open (no file with this name yet): ${r.join(", ")}`:""].filter(i=>i!=="").join(`
|
|
36
|
+
`))}catch(n){return w(G(n))}}}}import{z as l}from"zod";var nn=t=>({content:[{type:"text",text:t}]}),We=t=>({content:[{type:"text",text:t}],isError:!0});async function k(t){try{return nn(await t())}catch(e){if(e instanceof a){let n=Object.keys(e.params).length?` ${JSON.stringify(e.params)}`:"";return We(`${e.code}${n}`)}return We("errors.UNKNOWN")}}var O=l.string().min(1).max(32).regex(/^[a-z0-9]+(-[a-z0-9]+)*$/,"errors.INVALID_SLUG");async function F(t,e){let{connections:n}=await t.listConnections(),o=n.filter(r=>r.slug===e);return o.find(r=>r.scope==="personal")??o[0]??null}function oe(t){let e=t.authType==="none"?"no auth":`${t.authType}, secret ...${t.secretHint??"?"}`;return`${t.slug} \u2014 ${t.name} (${t.scope}, ${t.enabled?t.status:"disabled"}, ${e})
|
|
37
|
+
${t.url}${t.statusError?`
|
|
38
|
+
last error: ${t.statusError}`:""}`}var on=l.object({});function Be(t){return{name:"list_connections",description:"List the MCP servers connected through this OnlyMCP account, with the tool-name prefix each one uses.",inputSchema:on,handler:()=>k(async()=>{let{connections:e}=await t.listConnections();return e.length===0?"No MCP servers are connected yet. Add one with connection_create.":e.map(oe).join(`
|
|
39
|
+
`)})}}var rn=l.object({name:l.string().min(1).max(80),slug:O,url:l.string().url().max(2e3),transport:l.enum(["http","sse"]).default("http"),authType:l.enum(["none","bearer","header"]).default("none"),authHeaderName:l.string().max(80).optional(),secret:l.string().max(4e3).optional(),teamId:l.string().max(64).optional()});function Ve(t){return{name:"connection_create",description:"Connect a remote MCP server (http or sse only - a stdio server cannot be started on somebody else's behalf). It is probed straight away. Passing a secret here puts it into this conversation; leave it out and set it in the dashboard if that matters.",inputSchema:rn,handler:e=>k(async()=>{let{connection:n}=await t.createConnection(e);return`Connected.
|
|
40
|
+
${oe(n)}
|
|
41
|
+
|
|
42
|
+
Its tools are now available as "${n.slug}__<tool>".`})}}var sn=l.object({slug:O,name:l.string().min(1).max(80).optional(),url:l.string().url().max(2e3).optional(),transport:l.enum(["http","sse"]).optional(),authType:l.enum(["none","bearer","header"]).optional(),authHeaderName:l.string().max(80).optional(),secret:l.string().max(4e3).optional(),enabled:l.boolean().optional()});function Ke(t){return{name:"connection_update",description:"Change a connected MCP server. Only the fields you pass are touched; url, transport, authType and secret trigger a fresh probe.",inputSchema:sn,handler:e=>k(async()=>{let n=await F(t,e.slug);if(!n)return`Connection not found: ${e.slug}`;let{slug:o,...r}=e,{connection:i}=await t.updateConnection(n.id,r);return`Updated.
|
|
43
|
+
${oe(i)}`})}}var an=l.object({slug:O});function Je(t){return{name:"connection_delete",description:"Disconnect a remote MCP server and forget its stored credential. Its tools disappear from the gateway.",inputSchema:an,handler:e=>k(async()=>{let n=await F(t,e.slug);return n?(await t.deleteConnection(n.id),`Disconnected ${e.slug}.`):`Connection not found: ${e.slug}`})}}var ln=l.object({slug:O});function qe(t){return{name:"connection_tools",description:"List what one connected server offers, and whether each tool is switched on for the gateway.",inputSchema:ln,handler:e=>k(async()=>{let n=await F(t,e.slug);if(!n)return`Connection not found: ${e.slug}`;let{capabilities:o}=await t.listCapabilities(n.id);return o.length===0?`${e.slug} has nothing on record yet. Its status is "${n.status}".`:o.map(r=>`${r.enabled?"[on] ":"[off]"} ${r.kind} ${r.name}${r.exposedAs?` -> ${r.exposedAs}`:""}${r.description?` \u2014 ${r.description}`:""}`).join(`
|
|
44
|
+
`)})}}var cn=l.object({slug:O,tool:l.string().min(1).max(200),enabled:l.boolean()});function Ye(t){return{name:"connection_tool_toggle",description:"Switch one tool of a connected server on or off. A tool that is off costs no room in any client's tool list.",inputSchema:cn,handler:e=>k(async()=>{let n=await F(t,e.slug);if(!n)return`Connection not found: ${e.slug}`;let{capabilities:o}=await t.listCapabilities(n.id),r=o.find(i=>i.kind==="tool"&&i.name===e.tool);return r?(await t.toggleCapability(n.id,r.id,e.enabled),`${e.slug}__${r.name} is now ${e.enabled?"on":"off"}.`):`${e.slug} offers no tool called ${e.tool}.`})}}import{z as c}from"zod";var dn=t=>({content:[{type:"text",text:t}]}),N=t=>({content:[{type:"text",text:t}],isError:!0});async function v(t){try{return dn(await t())}catch(e){if(e instanceof a){let n=Object.keys(e.params).length?` ${JSON.stringify(e.params)}`:"";return N(`${e.code}${n}`)}return N("errors.UNKNOWN")}}var S=c.string().min(1).max(64).regex(/^[a-z0-9]+(-[a-z0-9]+)*$/,"errors.INVALID_NAME"),pn=c.object({name:S,body:c.string().max(2e5)});function Xe(t){return{name:"skill_write",description:"Create a skill or replace the body of an existing one. The body is the whole SKILL.md, frontmatter included.",inputSchema:pn,handler:e=>v(async()=>{let n=await t.putSkill(e.name,e.body);return`${n.name} ${n.updatedAt}`})}}var mn=c.object({name:S});function Ze(t){return{name:"skill_delete",description:"Delete one skill and every file that belongs to it. Moves it to the trash; it can be restored in the dashboard for the trash period (default 7 days).",inputSchema:mn,handler:e=>v(async()=>(await t.deleteSkill(e.name),`Deleted skill ${e.name}`))}}var un=c.object({skill:S});function Qe(t){return{name:"list_skill_files",description:"List the companion files of one skill, with their size in bytes.",inputSchema:un,handler:e=>v(async()=>{let{files:n}=await t.getSkill(e.skill);return n.length===0?`${e.skill} has no companion files.`:n.map(o=>`${o.path} (${o.size} bytes, ${o.encoding})`).join(`
|
|
45
|
+
`)})}}var hn=c.object({skill:S,path:c.string().min(1).max(256),content:c.string().max(3e6),encoding:c.enum(["utf8","base64"]).default("utf8")});function et(t){return{name:"skill_file_write",description:"Create or replace one companion file of a skill. Use encoding base64 for anything that is not text.",inputSchema:hn,handler:e=>I(e.path)?v(async()=>{let n=await t.putSkillFile(e.skill,e.path,e.content,e.encoding);return`${e.skill}/${n.path} ${n.size} bytes`}):Promise.resolve(N("errors.INVALID_PATH"))}}var gn=c.object({skill:S,path:c.string().min(1).max(256)});function tt(t){return{name:"skill_file_delete",description:"Delete one companion file of a skill. The skill itself stays.",inputSchema:gn,handler:e=>I(e.path)?v(async()=>(await t.deleteSkillFile(e.skill,e.path),`Deleted ${e.skill}/${e.path}`)):Promise.resolve(N("errors.INVALID_PATH"))}}var fn=c.object({name:S,description:c.string().min(1).max(1e3),body:c.string().max(2e5),model:c.string().max(64).optional(),tools:c.array(c.string().max(128)).max(200).optional()});function nt(t){return{name:"agent_write",description:"Create an agent or replace an existing one. Leave model out to keep the one it already has.",inputSchema:fn,handler:e=>v(async()=>{let n=await t.getAgent(e.name).catch(()=>null),o=await t.putAgent(e.name,{description:e.description,body:e.body,model:e.model??n?.model??void 0,tools:e.tools??n?.tools??[]});return`${o.name} ${o.updatedAt}`})}}var yn=c.object({name:S});function ot(t){return{name:"agent_delete",description:"Delete one agent. Moves it to the trash; it can be restored in the dashboard for the trash period (default 7 days).",inputSchema:yn,handler:e=>v(async()=>(await t.deleteAgent(e.name),`Deleted agent ${e.name}`))}}var bn=c.object({});function rt(t){return{name:"list_memory",description:"List the paths of every memory file in this account, private and team, sorted by path.",inputSchema:bn,handler:()=>v(async()=>{let{files:e}=await t.listMemory();return e.length===0?"(none)":e.map(n=>n.path+(n.scope==="team"?` (team${n.teamName?`: ${n.teamName}`:""})`:"")).sort().join(`
|
|
46
|
+
`)})}}var vn=c.object({path:c.string().min(3).max(256)});function it(t){return{name:"memory_delete",description:"Delete one memory file. Moves it to the trash; it can be restored in the dashboard for the trash period (default 7 days).",inputSchema:vn,handler:e=>y(e.path)?v(async()=>(await t.deleteMemory(e.path),`Deleted ${e.path}`)):Promise.resolve(N("errors.INVALID_PATH"))}}function st(t,e){return[Re(t),De(t),rt(t),it(t),je(t),Ge(t),Fe(t),He(t),Me(t),Le(t,e),Xe(t),Ze(t),Qe(t),Oe(t),et(t),tt(t),Pe(t),_e(t,e),nt(t),ot(t),Be(t),Ve(t),Ke(t),Je(t),qe(t),Ye(t)]}function at(t){return t.map(e=>{let n=ee[e.name];if(!n)throw new Error(`No title and annotations in the registry table for the tool ${e.name}`);return{name:e.name,title:n.title,description:e.description,inputSchema:Cn.toJSONSchema(e.inputSchema),annotations:n.annotations}})}async function lt(){let t=ve(),e=new P(t,()=>Ce.read()),n=new R,o=st(e,n),r=await(async()=>{try{let[{skills:d},{agents:u},g]=await Promise.all([e.listSkills(),e.listAgents(),e.getMe().catch(()=>({brainvaultMode:!0}))]);return K(d.map(f=>f.name),u.map(f=>f.name),{brainvault:g.brainvaultMode!==!1})}catch{return K([],[])}})(),i=new xn(J(t,M),{capabilities:{tools:{}},instructions:r});i.setRequestHandler(kn,async()=>({tools:at(o)})),i.setRequestHandler(wn,async d=>{let u=o.find(f=>f.name===d.params.name);if(!u)return{content:[{type:"text",text:"errors.UNKNOWN_TOOL"}],isError:!0};let g=u.inputSchema.safeParse(d.params.arguments??{});return g.success?u.handler(g.data):{content:[{type:"text",text:"errors.INVALID_ARGUMENTS"}],isError:!0}}),ke().then(d=>{for(let u of de())$e(e,u,{ignore:d}).catch(()=>{})}).catch(()=>{}),await i.connect(new Sn)}await lt();
|
package/package.json
CHANGED
|
@@ -1,16 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "onlymcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.20.0",
|
|
4
4
|
"description": "Skills, agents and memory from the OnlyMCP cloud in every MCP client. Ships the stdio MCP server and the CLI that sets up Claude Code, Codex and Antigravity.",
|
|
5
|
-
"license": "
|
|
5
|
+
"license": "SEE LICENSE IN LICENSE",
|
|
6
6
|
"author": "Francesco Palazzo",
|
|
7
7
|
"homepage": "https://only-mcp.com",
|
|
8
|
-
"
|
|
9
|
-
"type": "git",
|
|
10
|
-
"url": "git+https://github.com/Francesco070/onlymcp.git",
|
|
11
|
-
"directory": "packages/mcp"
|
|
12
|
-
},
|
|
13
|
-
"bugs": "https://github.com/Francesco070/onlymcp/issues",
|
|
8
|
+
"mcpName": "com.only-mcp/onlymcp",
|
|
14
9
|
"keywords": [
|
|
15
10
|
"mcp",
|
|
16
11
|
"model-context-protocol",
|
|
@@ -30,10 +25,11 @@
|
|
|
30
25
|
},
|
|
31
26
|
"files": [
|
|
32
27
|
"dist",
|
|
33
|
-
"README.md"
|
|
28
|
+
"README.md",
|
|
29
|
+
"LICENSE"
|
|
34
30
|
],
|
|
35
31
|
"scripts": {
|
|
36
|
-
"build": "
|
|
32
|
+
"build": "node build.mjs",
|
|
37
33
|
"typecheck": "tsc --noEmit",
|
|
38
34
|
"test": "node ../../scripts/sync-registry.mjs --check && vitest run",
|
|
39
35
|
"prepublishOnly": "pnpm build"
|
|
@@ -53,6 +49,7 @@
|
|
|
53
49
|
"@types/cacache": "^17.0.2",
|
|
54
50
|
"@types/node": "^22.15.0",
|
|
55
51
|
"@types/qrcode": "^1.5.5",
|
|
52
|
+
"esbuild": "^0.28.2",
|
|
56
53
|
"typescript": "^5.9.0",
|
|
57
54
|
"vitest": "^4.1.10"
|
|
58
55
|
}
|
package/dist/apiBaseUrl.d.ts
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The address of the OnlyMCP API that the stdio server talks to: ONLYMCP_API_URL, or https://only-mcp.com when the
|
|
3
|
-
* variable is not set. A variable that is set but empty is not "not set": it is a misconfiguration (an unexpanded
|
|
4
|
-
* `${VAR}` in an MCP client's config file lands here as the literal text).
|
|
5
|
-
*
|
|
6
|
-
* Fails fast and does not fall back: the stdio server has no degraded mode, every tool calls the API, and a guessed
|
|
7
|
-
* origin would hide the mistake. The message names the variable and shows the value, because the MCP client reports
|
|
8
|
-
* nothing but a closed connection; credentials in the value (`user:pass@`) are masked, as stderr ends up in client logs.
|
|
9
|
-
* Only http: and https: are accepted.
|
|
10
|
-
*/
|
|
11
|
-
export declare const DEFAULT_API_URL = "https://only-mcp.com";
|
|
12
|
-
export declare function apiBaseUrl(raw?: string | undefined): string;
|
package/dist/apiBaseUrl.js
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The address of the OnlyMCP API that the stdio server talks to: ONLYMCP_API_URL, or https://only-mcp.com when the
|
|
3
|
-
* variable is not set. A variable that is set but empty is not "not set": it is a misconfiguration (an unexpanded
|
|
4
|
-
* `${VAR}` in an MCP client's config file lands here as the literal text).
|
|
5
|
-
*
|
|
6
|
-
* Fails fast and does not fall back: the stdio server has no degraded mode, every tool calls the API, and a guessed
|
|
7
|
-
* origin would hide the mistake. The message names the variable and shows the value, because the MCP client reports
|
|
8
|
-
* nothing but a closed connection; credentials in the value (`user:pass@`) are masked, as stderr ends up in client logs.
|
|
9
|
-
* Only http: and https: are accepted.
|
|
10
|
-
*/
|
|
11
|
-
export const DEFAULT_API_URL = 'https://only-mcp.com';
|
|
12
|
-
export function apiBaseUrl(raw = process.env.ONLYMCP_API_URL) {
|
|
13
|
-
if (raw === undefined)
|
|
14
|
-
return DEFAULT_API_URL;
|
|
15
|
-
let protocol;
|
|
16
|
-
try {
|
|
17
|
-
protocol = new URL(raw).protocol;
|
|
18
|
-
}
|
|
19
|
-
catch {
|
|
20
|
-
// Not parseable at all: reported below like a wrong scheme.
|
|
21
|
-
}
|
|
22
|
-
if (protocol !== 'http:' && protocol !== 'https:') {
|
|
23
|
-
const shown = raw.replace(/\/\/[^/@]*@/, '//***@');
|
|
24
|
-
throw new Error(`ONLYMCP_API_URL is not a valid http(s) URL: ${JSON.stringify(shown)}`);
|
|
25
|
-
}
|
|
26
|
-
return raw;
|
|
27
|
-
}
|
|
28
|
-
//# sourceMappingURL=apiBaseUrl.js.map
|
package/dist/apiBaseUrl.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"apiBaseUrl.js","sourceRoot":"","sources":["../src/apiBaseUrl.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,sBAAsB,CAAC;AAEtD,MAAM,UAAU,UAAU,CAAC,MAA0B,OAAO,CAAC,GAAG,CAAC,eAAe;IAC9E,IAAI,GAAG,KAAK,SAAS;QAAE,OAAO,eAAe,CAAC;IAC9C,IAAI,QAA4B,CAAC;IACjC,IAAI,CAAC;QACH,QAAQ,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC;IACnC,CAAC;IAAC,MAAM,CAAC;QACP,4DAA4D;IAC9D,CAAC;IACD,IAAI,QAAQ,KAAK,OAAO,IAAI,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAClD,MAAM,KAAK,GAAG,GAAG,CAAC,OAAO,CAAC,aAAa,EAAE,QAAQ,CAAC,CAAC;QACnD,MAAM,IAAI,KAAK,CAAC,+CAA+C,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAC1F,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
|
package/dist/apiClient.d.ts
DELETED
|
@@ -1,296 +0,0 @@
|
|
|
1
|
-
export declare class ApiError extends Error {
|
|
2
|
-
readonly code: string;
|
|
3
|
-
readonly params: Record<string, unknown>;
|
|
4
|
-
readonly status: number;
|
|
5
|
-
constructor(code: string, params?: Record<string, unknown>, status?: number);
|
|
6
|
-
}
|
|
7
|
-
/**
|
|
8
|
-
* Herkunft und Bearbeitbarkeit, wie jede Liste des Servers sie mitschickt
|
|
9
|
-
* (teams/scope.ts). Der Client braucht sie fuer `--prune`: geloescht wird nur,
|
|
10
|
-
* was diesem Konto allein gehoert.
|
|
11
|
-
*/
|
|
12
|
-
export type Scoped = {
|
|
13
|
-
scope: 'personal' | 'team';
|
|
14
|
-
teamName: string | null;
|
|
15
|
-
isOwn: boolean;
|
|
16
|
-
canEdit: boolean;
|
|
17
|
-
archivedAt: string | null;
|
|
18
|
-
};
|
|
19
|
-
/** Die Sammlung, aus der ein Skill stammt (Paket 03 Aufgabe 11). */
|
|
20
|
-
export type SkillCollection = {
|
|
21
|
-
key: string;
|
|
22
|
-
kind: string;
|
|
23
|
-
label: string;
|
|
24
|
-
};
|
|
25
|
-
export type SkillProvenance = {
|
|
26
|
-
description?: string;
|
|
27
|
-
sourcePath?: string;
|
|
28
|
-
collection?: {
|
|
29
|
-
key: string;
|
|
30
|
-
kind: string;
|
|
31
|
-
label?: string;
|
|
32
|
-
} | null;
|
|
33
|
-
};
|
|
34
|
-
export type SkillListItem = Scoped & {
|
|
35
|
-
name: string;
|
|
36
|
-
description: string;
|
|
37
|
-
collection: SkillCollection | null;
|
|
38
|
-
updatedAt: string;
|
|
39
|
-
};
|
|
40
|
-
export type AgentListItem = Scoped & {
|
|
41
|
-
name: string;
|
|
42
|
-
description: string;
|
|
43
|
-
model: string | null;
|
|
44
|
-
tools: string[];
|
|
45
|
-
updatedAt: string;
|
|
46
|
-
};
|
|
47
|
-
export type SkillFileMeta = {
|
|
48
|
-
path: string;
|
|
49
|
-
encoding: FileEncoding;
|
|
50
|
-
size: number;
|
|
51
|
-
updatedAt: string;
|
|
52
|
-
};
|
|
53
|
-
export type SkillFile = SkillFileMeta & {
|
|
54
|
-
content: string;
|
|
55
|
-
};
|
|
56
|
-
export type FileEncoding = 'utf8' | 'base64';
|
|
57
|
-
export type MemoryFile = {
|
|
58
|
-
path: string;
|
|
59
|
-
content: string;
|
|
60
|
-
frontmatter: Record<string, unknown>;
|
|
61
|
-
links: {
|
|
62
|
-
resolved: string[];
|
|
63
|
-
unresolved: string[];
|
|
64
|
-
};
|
|
65
|
-
updatedAt: string;
|
|
66
|
-
updatedByDevice: string | null;
|
|
67
|
-
updatedByName?: string | null;
|
|
68
|
-
};
|
|
69
|
-
export type SearchHit = {
|
|
70
|
-
kind: 'memory' | 'skill' | 'agent';
|
|
71
|
-
id: string;
|
|
72
|
-
name: string;
|
|
73
|
-
path: string | null;
|
|
74
|
-
snippet: string;
|
|
75
|
-
scope: 'personal' | 'team';
|
|
76
|
-
teamId: string | null;
|
|
77
|
-
};
|
|
78
|
-
export type TreeEntry = {
|
|
79
|
-
kind: 'folder' | 'file';
|
|
80
|
-
path: string;
|
|
81
|
-
name: string;
|
|
82
|
-
type: string | null;
|
|
83
|
-
updatedAt: string | null;
|
|
84
|
-
scope: 'personal' | 'team';
|
|
85
|
-
teamName: string | null;
|
|
86
|
-
canEdit: boolean;
|
|
87
|
-
};
|
|
88
|
-
export type MemoryListItem = Scoped & {
|
|
89
|
-
path: string;
|
|
90
|
-
updatedAt: string;
|
|
91
|
-
};
|
|
92
|
-
export type Connection = {
|
|
93
|
-
id: string;
|
|
94
|
-
name: string;
|
|
95
|
-
slug: string;
|
|
96
|
-
url: string;
|
|
97
|
-
transport: string;
|
|
98
|
-
authType: string;
|
|
99
|
-
authHeaderName: string | null;
|
|
100
|
-
secretHint: string | null;
|
|
101
|
-
enabled: boolean;
|
|
102
|
-
status: string;
|
|
103
|
-
statusError: string | null;
|
|
104
|
-
scope: 'personal' | 'team';
|
|
105
|
-
can?: {
|
|
106
|
-
edit: boolean;
|
|
107
|
-
delete: boolean;
|
|
108
|
-
toggleTools: boolean;
|
|
109
|
-
manageCredentials: boolean;
|
|
110
|
-
};
|
|
111
|
-
};
|
|
112
|
-
export type Capability = {
|
|
113
|
-
id: string;
|
|
114
|
-
kind: 'tool' | 'resource' | 'prompt';
|
|
115
|
-
name: string;
|
|
116
|
-
description: string;
|
|
117
|
-
enabled: boolean;
|
|
118
|
-
exposedAs: string | null;
|
|
119
|
-
};
|
|
120
|
-
export type ConnectionInput = {
|
|
121
|
-
name: string;
|
|
122
|
-
slug: string;
|
|
123
|
-
url: string;
|
|
124
|
-
transport?: 'http' | 'sse';
|
|
125
|
-
authType?: 'none' | 'bearer' | 'header';
|
|
126
|
-
authHeaderName?: string;
|
|
127
|
-
secret?: string;
|
|
128
|
-
teamId?: string | null;
|
|
129
|
-
};
|
|
130
|
-
export type WriteResult = {
|
|
131
|
-
path: string;
|
|
132
|
-
updatedAt: string;
|
|
133
|
-
warning?: {
|
|
134
|
-
code: string;
|
|
135
|
-
params: Record<string, unknown>;
|
|
136
|
-
};
|
|
137
|
-
/** Set when the server created the file in a team instead of the personal space. */
|
|
138
|
-
routedTo?: {
|
|
139
|
-
teamId: string;
|
|
140
|
-
teamName: string;
|
|
141
|
-
};
|
|
142
|
-
};
|
|
143
|
-
export declare class ApiClient {
|
|
144
|
-
private readonly baseUrl;
|
|
145
|
-
private readonly token;
|
|
146
|
-
constructor(baseUrl: string, token: () => string | null);
|
|
147
|
-
private call;
|
|
148
|
-
getMe(): Promise<{
|
|
149
|
-
id: string;
|
|
150
|
-
email: string;
|
|
151
|
-
plan: {
|
|
152
|
-
name: string;
|
|
153
|
-
};
|
|
154
|
-
/** Optional, weil eine aeltere API sie nicht schickt. Fehlt sie, gilt an. */
|
|
155
|
-
brainvaultMode?: boolean;
|
|
156
|
-
}>;
|
|
157
|
-
/**
|
|
158
|
-
* Tells the server this device just finished an import or a sync (POST
|
|
159
|
-
* /api/devices/current/run), so the devices page can show when and how many files. The caller
|
|
160
|
-
* treats a failure as nothing: an older server answers 404, and a report is never worth a
|
|
161
|
-
* failed command. Five seconds at most, so a slow server cannot hold the command up.
|
|
162
|
-
*/
|
|
163
|
-
reportRun(kind: 'import' | 'sync', files: number): Promise<void>;
|
|
164
|
-
/**
|
|
165
|
-
* Ends this device's session on the server (POST /api/auth/sign-out, Better Auth's own sign-out:
|
|
166
|
-
* the API's bearer plugin turns the token into the session cookie that endpoint reads). For
|
|
167
|
-
* `onlymcp logout`, which forgets the login on this machine whatever this answers. Five seconds
|
|
168
|
-
* at most, so an unreachable server cannot hold the logout up.
|
|
169
|
-
*/
|
|
170
|
-
signOut(): Promise<{
|
|
171
|
-
success: boolean;
|
|
172
|
-
}>;
|
|
173
|
-
listSkills(): Promise<{
|
|
174
|
-
skills: SkillListItem[];
|
|
175
|
-
}>;
|
|
176
|
-
getSkill(name: string): Promise<{
|
|
177
|
-
name: string;
|
|
178
|
-
body: string;
|
|
179
|
-
description: string;
|
|
180
|
-
collection: SkillCollection | null;
|
|
181
|
-
sourcePath: string | null;
|
|
182
|
-
updatedAt: string;
|
|
183
|
-
files: SkillFileMeta[];
|
|
184
|
-
}>;
|
|
185
|
-
/**
|
|
186
|
-
* Die Herkunft ist optional und wird WEGGELASSEN, nicht auf leer gesetzt,
|
|
187
|
-
* wenn es keine gibt: ein fehlendes Feld heisst serverseitig "nicht
|
|
188
|
-
* anfassen" (Spec 5, Regel 1). Ein `description: ''` mitzuschicken loeschte
|
|
189
|
-
* die Beschreibung, die ein frueherer Import geschrieben hat.
|
|
190
|
-
*/
|
|
191
|
-
putSkill(name: string, body: string, provenance?: SkillProvenance): Promise<{
|
|
192
|
-
name: string;
|
|
193
|
-
updatedAt: string;
|
|
194
|
-
}>;
|
|
195
|
-
private skillFileUrl;
|
|
196
|
-
getSkillFile(name: string, path: string): Promise<SkillFile>;
|
|
197
|
-
putSkillFile(name: string, path: string, content: string, encoding?: FileEncoding): Promise<{
|
|
198
|
-
path: string;
|
|
199
|
-
size: number;
|
|
200
|
-
updatedAt: string;
|
|
201
|
-
}>;
|
|
202
|
-
listAgents(): Promise<{
|
|
203
|
-
agents: AgentListItem[];
|
|
204
|
-
}>;
|
|
205
|
-
putAgent(name: string, a: {
|
|
206
|
-
description: string;
|
|
207
|
-
model?: string;
|
|
208
|
-
tools: string[];
|
|
209
|
-
body: string;
|
|
210
|
-
}): Promise<{
|
|
211
|
-
name: string;
|
|
212
|
-
updatedAt: string;
|
|
213
|
-
}>;
|
|
214
|
-
/**
|
|
215
|
-
* `use` says "I am loading this definition to run it", and the server counts
|
|
216
|
-
* a load for the agent's "Used" line. Only `get_agent_definition` asks. Any
|
|
217
|
-
* other read of the same route (the write tool looking at the previous state)
|
|
218
|
-
* is not a use and must not send it.
|
|
219
|
-
*/
|
|
220
|
-
getAgent(name: string, { use }?: {
|
|
221
|
-
use?: boolean;
|
|
222
|
-
}): Promise<Scoped & {
|
|
223
|
-
name: string;
|
|
224
|
-
description: string;
|
|
225
|
-
model: string | null;
|
|
226
|
-
tools: string[];
|
|
227
|
-
updatedAt: string;
|
|
228
|
-
} & {
|
|
229
|
-
body: string;
|
|
230
|
-
}>;
|
|
231
|
-
readMemory(path: string): Promise<MemoryFile>;
|
|
232
|
-
writeMemory(path: string, content: string, deviceLabel?: string): Promise<WriteResult>;
|
|
233
|
-
private memoryUrl;
|
|
234
|
-
listMemory(): Promise<{
|
|
235
|
-
files: MemoryListItem[];
|
|
236
|
-
}>;
|
|
237
|
-
searchContent(q: string, opts?: {
|
|
238
|
-
types?: string[];
|
|
239
|
-
limit?: number;
|
|
240
|
-
}): Promise<{
|
|
241
|
-
hits: SearchHit[];
|
|
242
|
-
}>;
|
|
243
|
-
memoryTree(scope?: string): Promise<{
|
|
244
|
-
nodes: TreeEntry[];
|
|
245
|
-
}>;
|
|
246
|
-
/**
|
|
247
|
-
* A move is a write of the moved file and of every file whose links it rewrites, and the
|
|
248
|
-
* server records the device each write came from. This machine's host name, as the
|
|
249
|
-
* memory_write tool and the import name it, so a write and a move from here are one device.
|
|
250
|
-
*/
|
|
251
|
-
moveMemory(from: string, to: string, updateLinks?: boolean, deviceLabel?: string): Promise<{
|
|
252
|
-
from: string;
|
|
253
|
-
to: string;
|
|
254
|
-
rewritten: number;
|
|
255
|
-
skipped: number;
|
|
256
|
-
}>;
|
|
257
|
-
/**
|
|
258
|
-
* Das Export-Archiv, als ROHE Antwort.
|
|
259
|
-
*
|
|
260
|
-
* Geht bewusst nicht durch `call`: das dort ist ein JSON-Client, und ein
|
|
261
|
-
* Archiv von zwei Gigabyte durch `res.json()` zu schicken waere genau der
|
|
262
|
-
* Fehler, den die Route auf ihrer Seite vermeidet. Der Aufrufer bekommt den
|
|
263
|
-
* Strom und entscheidet, ob er ihn in eine Datei giesst oder auspackt.
|
|
264
|
-
*/
|
|
265
|
-
exportArchive(opts?: {
|
|
266
|
-
scope?: string;
|
|
267
|
-
types?: string[];
|
|
268
|
-
}): Promise<Response>;
|
|
269
|
-
deleteMemory(path: string): Promise<void>;
|
|
270
|
-
deleteSkill(name: string): Promise<void>;
|
|
271
|
-
deleteSkillFile(name: string, path: string): Promise<void>;
|
|
272
|
-
deleteAgent(name: string): Promise<void>;
|
|
273
|
-
listConnections(): Promise<{
|
|
274
|
-
connections: Connection[];
|
|
275
|
-
}>;
|
|
276
|
-
createConnection(input: ConnectionInput): Promise<{
|
|
277
|
-
connection: Connection;
|
|
278
|
-
}>;
|
|
279
|
-
updateConnection(id: string, patch: Partial<ConnectionInput> & {
|
|
280
|
-
enabled?: boolean;
|
|
281
|
-
}): Promise<{
|
|
282
|
-
connection: Connection;
|
|
283
|
-
}>;
|
|
284
|
-
deleteConnection(id: string): Promise<{
|
|
285
|
-
ok: boolean;
|
|
286
|
-
}>;
|
|
287
|
-
listCapabilities(id: string): Promise<{
|
|
288
|
-
capabilities: Capability[];
|
|
289
|
-
}>;
|
|
290
|
-
toggleCapability(id: string, capId: string, enabled: boolean): Promise<{
|
|
291
|
-
capability: {
|
|
292
|
-
id: string;
|
|
293
|
-
enabled: boolean;
|
|
294
|
-
};
|
|
295
|
-
}>;
|
|
296
|
-
}
|