kloudy 0.4.2 → 0.4.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 CHANGED
@@ -6,7 +6,7 @@ npx kloudy find github MCP tools
6
6
  npx kloudy mcp
7
7
  ```
8
8
 
9
- Node.js 20.19+ is required. Run `npx kloudy` to install, or `npx kloudy@0.4.2` to pin this release. A downloadable tarball is also available at https://kloudy.ai/downloads/kloudy-open-0.4.2.tgz.
9
+ Node.js 20.19+ is required. Run `npx kloudy` to install, or `npx kloudy@0.4.3` to pin this release. A downloadable tarball is also available at https://kloudy.ai/downloads/kloudy-open-0.4.3.tgz.
10
10
 
11
11
  No arguments detects Cursor, VS Code, Claude Desktop, Claude Code, Windsurf and Codex configurations and asks before writing **each** one. Declining or non-interactive input changes nothing. Existing servers and existing Kloudy entries are preserved. JSONC comments in VS Code and TOML comments in Codex remain intact. Backups are created; malformed or concurrently changed configs are left untouched. Normal OS file permissions apply on Windows; protect config files that contain keys.
12
12
 
@@ -303,3 +303,5 @@ MCP: operation `conversation`, `conversation_operation` = `read`, `append` or `s
303
303
  `append` takes `project`, `conversation_id`, `idempotency_key`, `expected_revision`, `title`, `user`, `assistant`, `decisions` and `built_artifacts`. Use a stable idempotency key for the same exchange, an explicitly observed revision, up to 1500 characters per message, four decisions/artifact pointers at most, and a total canonical request no larger than 7000 bytes. Send only content the user authorized for sync. A new conversation explicitly starts at revision zero. `sync` takes the same cursor/idempotency fields plus `reason`: `checkpoint`, `session_end`, `device_switch`, `before_sync` or `idle`.
304
304
 
305
305
  The engine owns encryption, scope checks, condensation gates and transcript deletion. Returned cards are lossy context, never grants. Artifact pointers do not authorize repository reads. The client never persists message bodies in its session file. Replayed commands return metadata only: issue a read for current cards. Conflicts and failures are not retried automatically; read the cursor and reconcile before resubmitting. Added in 0.4.1. The no-key installer and public discovery remain unchanged.
306
+
307
+ Official MCP Registry name: `ai.kloudy/kloudy`. Remote endpoint: https://kloudy.ai/mcp. Public discovery and Sample cards do not grant private tools or authorize spending.
package/bin/entry.mjs CHANGED
@@ -1,4 +1,6 @@
1
1
  #!/usr/bin/env node
2
+ import {readFileSync} from 'node:fs';
3
+ const version=JSON.parse(readFileSync(new URL('../package.json',import.meta.url),'utf8')).version;
2
4
  import {createInterface} from 'node:readline/promises';
3
5
  import {installEditors} from '../src/editor-install.mjs';
4
6
  import {askRemote,serveRemote} from '../src/remote.mjs';
@@ -9,11 +11,11 @@ try{
9
11
  let rl;
10
12
  const confirm=async({client,path,authenticated})=>{if(!process.stdin.isTTY){console.log(`${client}: skipped — run in an interactive terminal to approve ${path}`);return false;}rl??=createInterface({input:process.stdin,output:process.stdout});return /^(y|yes)$/i.test((await rl.question(`Add Kloudy to ${client}? ${path}${authenticated?' (stores your key)':''} [y/N] `)).trim());};
11
13
  let results;try{results=await installEditors({confirm,key:process.env.KLOUDY_MCP_TOKEN,onResult:r=>console.log(`${r.client}: ${r.state}`)});}finally{rl?.close();}
12
- if(!results.length)console.log('No supported editor configuration found. Open https://kloudy.ai/install for one-click Cursor and VS Code links.');
14
+ if(!results.length)console.log('No supported editor configuration found. Open https://kloudy.ai/install for setup help.');
13
15
  else console.log('Existing servers were preserved. Restart configured clients to connect.');
14
16
  if(results.some(r=>r.state==='unchanged_error'))process.exitCode=1;
15
17
  }else if(args[0]==='mcp'&&args.length===1){await serveRemote();}
16
- else if(args[0]==='--version'){console.log('0.4.2');}
18
+ else if(args[0]==='--version'){console.log(version);}
17
19
  else if(['--help','help'].includes(args[0]))console.log('npx kloudy Add to detected editors (asks before each write)\nnpx kloudy <question> Ask the public Kloudy MCP endpoint\nnpx kloudy mcp Remote MCP over local stdio\nnpx kloudy legacy <args> Existing SDK/engine CLI commands\n\nFree discovery needs no key. For authorized account actions set KLOUDY_MCP_TOKEN privately; never put a key in command arguments. Node 20.19+ required.');
18
20
  else if(args[0]==='legacy'){process.argv.splice(2,1);await import('./kloudy.mjs');}
19
21
  else{if(args[0]?.startsWith('--'))throw Error('Unknown option');const result=await askRemote(args.join(' '));for(const c of result.content||[])if(c.type==='text')process.stdout.write((process.env.KLOUDY_MCP_TOKEN?c.text.replaceAll(process.env.KLOUDY_MCP_TOKEN,'[redacted]'):c.text)+'\n');if(result.isError)process.exitCode=1;}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kloudy",
3
- "version": "0.4.2",
3
+ "version": "0.4.4",
4
4
  "description": "Ask for Kloudy: CLI, MCP and SDK clients for the same scoped engine session.",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -56,7 +56,7 @@
56
56
  "devDependencies": {
57
57
  "esbuild": "0.28.2"
58
58
  },
59
- "mcpName": "io.github.Gio300/kloudy",
59
+ "mcpName": "ai.kloudy/kloudy",
60
60
  "homepage": "https://kloudy.ai/install",
61
61
  "publishConfig": {
62
62
  "access": "public",
@@ -0,0 +1,36 @@
1
+ import {connectHTML,publicConnectHTML} from './connect-ui.mjs';
2
+
3
+ export const CONNECT_URI='ui://widget/kloudy-connect-v1.html';
4
+ export const connectResource={uri:CONNECT_URI,name:'Kloudy setup',description:'Sign in or choose a Kloudy front door. Navigation only.',mimeType:'text/html;profile=mcp-app'};
5
+ export const connectTool={
6
+ name:'kloudy_connect_card',
7
+ title:'Kloudy sign-in and install card',
8
+ description:'Show sign-in or install choices. First call find_mcp_tools with operation ask and a short setup request. If it returns kind account or connect, call this card once with the returned mode. Opening setup does not finish sign-in or installation. Text-only hosts show the returned links.',
9
+ annotations:{readOnlyHint:true,destructiveHint:false,idempotentHint:true,openWorldHint:false},
10
+ inputSchema:{type:'object',properties:{mode:{type:'string',enum:['signin','install'],description:'Use the mode returned by find_mcp_tools: signin for account sign-in, or install for editor setup.'}},required:['mode'],additionalProperties:false},
11
+ _meta:{ui:{resourceUri:CONNECT_URI},'openai/outputTemplate':CONNECT_URI,'openai/toolInvocation/invoking':'Opening Kloudy setup…','openai/toolInvocation/invoked':'Kloudy setup choices'}
12
+ };
13
+ export function connectArguments(value){return !!value&&typeof value==='object'&&!Array.isArray(value)&&Object.keys(value).length===1&&['signin','install'].includes(value.mode);}
14
+ export function connectResult(mode,{publicOnly=false}={}){
15
+ const install=mode==='install';
16
+ const message=install?'Choose where to connect Kloudy. Opening setup is not a finished connection.':'Kloudy finds MCP tools and SDKs for your task. Sign in or keep using free discovery.';
17
+ const actions=install?[
18
+ {label:'Add to an IDE',url:'https://kloudy.ai/install#clients'},
19
+ ...(!publicOnly?[{label:'Connect to Muse',url:'https://kloudy.ai/install#muse'}]:[]),
20
+ {label:'Sign in',url:'https://kloudy.ai/install'}
21
+ ]:[{label:'Sign in to Kloudy',url:'https://kloudy.ai/install'},{label:'Add to an IDE',url:'https://kloudy.ai/install#clients'}];
22
+ return {content:[{type:'text',text:message+'\n\n'+actions.map(a=>`[${a.label}](${a.url})`).join('\n')}],structuredContent:{tier:'public',kind:install?'connect':'account',mode,items:[],message,actions,model_calls:0,executed:false}};
23
+ }
24
+ export function connectContents({publicOnly=false}={}){return {contents:[{uri:CONNECT_URI,mimeType:connectResource.mimeType,text:publicOnly?publicConnectHTML:connectHTML,_meta:{
25
+ ui:{prefersBorder:true,domain:'https://kloudy.ai',csp:{connectDomains:[],resourceDomains:[]}},
26
+ 'openai/widgetDescription':'Kloudy sign-in and setup choices. No account is created and no tool is authorized by opening a link.',
27
+ 'openai/widgetPrefersBorder':true,'openai/widgetDomain':'https://kloudy.ai',
28
+ 'openai/widgetCSP':{connect_domains:[],resource_domains:[],redirect_domains:['https://kloudy.ai','https://cursor.com','https://insiders.vscode.dev']}
29
+ }}]};}
30
+ // Public UI metadata still requires credential validation when called with a credential.
31
+ export function connectMessage(method,params={}){
32
+ if(!params||typeof params!=='object'||Array.isArray(params))return false;
33
+ if(['resources/list','resources/templates/list'].includes(method))return Object.keys(params).length===0;
34
+ if(method==='resources/read')return Object.keys(params).length===1&&params.uri===CONNECT_URI;
35
+ return method==='tools/call'&&Object.keys(params).length===2&&params.name==='kloudy_connect_card'&&connectArguments(params.arguments);
36
+ }