kloudy 0.4.6 → 0.4.7
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 +5 -0
- package/package.json +68 -68
- package/src/chooser-link.mjs +17 -0
- package/src/remote.mjs +18 -2
package/README.md
CHANGED
|
@@ -307,3 +307,8 @@ MCP: operation `conversation`, `conversation_operation` = `read`, `append` or `s
|
|
|
307
307
|
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.
|
|
308
308
|
|
|
309
309
|
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.
|
|
310
|
+
|
|
311
|
+
## Card and website fallback (0.4.7)
|
|
312
|
+
|
|
313
|
+
The remote MCP adapter returns supported card metadata and a plain-text HTTPS chooser link together. Hosts control rendering and link launch. Call show_pending_chooser_link to display the last offer/selection again in the same MCP process. Website sign-in verifies private account projects; the public template locator is never an account token or authorization. A presentation goal may be retained in the current MCP process and is kept out of the URL. Automatic authenticated IDE return is not claimed. If the process resets, use the website's existing project recovery path. No models, installation or spending are activated by these links.
|
|
314
|
+
|
package/package.json
CHANGED
|
@@ -1,68 +1,68 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "kloudy",
|
|
3
|
-
"version": "0.4.
|
|
4
|
-
"description": "Ask for Kloudy: CLI, MCP and SDK clients for the same scoped engine session.",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"license": "Apache-2.0",
|
|
7
|
-
"engines": {
|
|
8
|
-
"node": ">=20.19.0"
|
|
9
|
-
},
|
|
10
|
-
"bin": {
|
|
11
|
-
"kloudy": "bin/entry.mjs"
|
|
12
|
-
},
|
|
13
|
-
"exports": {
|
|
14
|
-
".": "./src/client.mjs",
|
|
15
|
-
"./mcp": "./src/mcp.mjs",
|
|
16
|
-
"./wrap": "./src/wrap.mjs",
|
|
17
|
-
"./session": "./src/connection.mjs",
|
|
18
|
-
"./httpk": "./src/httpk.mjs",
|
|
19
|
-
"./hosted": "./src/hosted.mjs",
|
|
20
|
-
"./public": "./src/public.mjs",
|
|
21
|
-
"./strings": "./src/strings.mjs",
|
|
22
|
-
"./sdf": "./src/sdf.mjs",
|
|
23
|
-
"./query": "./src/query.mjs",
|
|
24
|
-
"./activity": "./src/activity.mjs",
|
|
25
|
-
"./status-indicator.css": "./src/status-indicator.css",
|
|
26
|
-
"./models": "./src/models.mjs",
|
|
27
|
-
"./host-interface": "./src/host-interface.mjs",
|
|
28
|
-
"./replies": "./src/replies.mjs",
|
|
29
|
-
"./conversation": "./src/conversation.mjs"
|
|
30
|
-
},
|
|
31
|
-
"files": [
|
|
32
|
-
"bin",
|
|
33
|
-
"src",
|
|
34
|
-
"schemas",
|
|
35
|
-
"README.md",
|
|
36
|
-
"MCP-DEFAULT.md",
|
|
37
|
-
"LICENSE"
|
|
38
|
-
],
|
|
39
|
-
"scripts": {
|
|
40
|
-
"test": "node --test test/*.test.mjs",
|
|
41
|
-
"check": "node --check bin/kloudy.mjs && node --check src/client.mjs && npm test",
|
|
42
|
-
"start": "node bin/kloudy.mjs",
|
|
43
|
-
"proof": "node scripts/prove.mjs",
|
|
44
|
-
"build:approval": "node scripts/build-approval.mjs"
|
|
45
|
-
},
|
|
46
|
-
"dependencies": {
|
|
47
|
-
"@modelcontextprotocol/ext-apps": "2.0.3",
|
|
48
|
-
"@modelcontextprotocol/sdk": "1.31.0",
|
|
49
|
-
"ajv": "8.20.0",
|
|
50
|
-
"ajv-formats": "3.0.1",
|
|
51
|
-
"js-tiktoken": "1.0.21",
|
|
52
|
-
"jsonc-parser": "3.3.1",
|
|
53
|
-
"smol-toml": "1.9.0",
|
|
54
|
-
"zod": "4.6.5"
|
|
55
|
-
},
|
|
56
|
-
"devDependencies": {
|
|
57
|
-
"esbuild": "0.28.2"
|
|
58
|
-
},
|
|
59
|
-
"mcpName": "ai.kloudy/kloudy",
|
|
60
|
-
"homepage": "https://kloudy.ai/install",
|
|
61
|
-
"publishConfig": {
|
|
62
|
-
"access": "public",
|
|
63
|
-
"registry": "https://registry.npmjs.org"
|
|
64
|
-
},
|
|
65
|
-
"bugs": {
|
|
66
|
-
"url": "https://kloudy.ai/support"
|
|
67
|
-
}
|
|
68
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "kloudy",
|
|
3
|
+
"version": "0.4.7",
|
|
4
|
+
"description": "Ask for Kloudy: CLI, MCP and SDK clients for the same scoped engine session.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "Apache-2.0",
|
|
7
|
+
"engines": {
|
|
8
|
+
"node": ">=20.19.0"
|
|
9
|
+
},
|
|
10
|
+
"bin": {
|
|
11
|
+
"kloudy": "bin/entry.mjs"
|
|
12
|
+
},
|
|
13
|
+
"exports": {
|
|
14
|
+
".": "./src/client.mjs",
|
|
15
|
+
"./mcp": "./src/mcp.mjs",
|
|
16
|
+
"./wrap": "./src/wrap.mjs",
|
|
17
|
+
"./session": "./src/connection.mjs",
|
|
18
|
+
"./httpk": "./src/httpk.mjs",
|
|
19
|
+
"./hosted": "./src/hosted.mjs",
|
|
20
|
+
"./public": "./src/public.mjs",
|
|
21
|
+
"./strings": "./src/strings.mjs",
|
|
22
|
+
"./sdf": "./src/sdf.mjs",
|
|
23
|
+
"./query": "./src/query.mjs",
|
|
24
|
+
"./activity": "./src/activity.mjs",
|
|
25
|
+
"./status-indicator.css": "./src/status-indicator.css",
|
|
26
|
+
"./models": "./src/models.mjs",
|
|
27
|
+
"./host-interface": "./src/host-interface.mjs",
|
|
28
|
+
"./replies": "./src/replies.mjs",
|
|
29
|
+
"./conversation": "./src/conversation.mjs"
|
|
30
|
+
},
|
|
31
|
+
"files": [
|
|
32
|
+
"bin",
|
|
33
|
+
"src",
|
|
34
|
+
"schemas",
|
|
35
|
+
"README.md",
|
|
36
|
+
"MCP-DEFAULT.md",
|
|
37
|
+
"LICENSE"
|
|
38
|
+
],
|
|
39
|
+
"scripts": {
|
|
40
|
+
"test": "node --test test/*.test.mjs",
|
|
41
|
+
"check": "node --check bin/kloudy.mjs && node --check src/client.mjs && npm test",
|
|
42
|
+
"start": "node bin/kloudy.mjs",
|
|
43
|
+
"proof": "node scripts/prove.mjs",
|
|
44
|
+
"build:approval": "node scripts/build-approval.mjs"
|
|
45
|
+
},
|
|
46
|
+
"dependencies": {
|
|
47
|
+
"@modelcontextprotocol/ext-apps": "2.0.3",
|
|
48
|
+
"@modelcontextprotocol/sdk": "1.31.0",
|
|
49
|
+
"ajv": "8.20.0",
|
|
50
|
+
"ajv-formats": "3.0.1",
|
|
51
|
+
"js-tiktoken": "1.0.21",
|
|
52
|
+
"jsonc-parser": "3.3.1",
|
|
53
|
+
"smol-toml": "1.9.0",
|
|
54
|
+
"zod": "4.6.5"
|
|
55
|
+
},
|
|
56
|
+
"devDependencies": {
|
|
57
|
+
"esbuild": "0.28.2"
|
|
58
|
+
},
|
|
59
|
+
"mcpName": "ai.kloudy/kloudy",
|
|
60
|
+
"homepage": "https://kloudy.ai/install",
|
|
61
|
+
"publishConfig": {
|
|
62
|
+
"access": "public",
|
|
63
|
+
"registry": "https://registry.npmjs.org"
|
|
64
|
+
},
|
|
65
|
+
"bugs": {
|
|
66
|
+
"url": "https://kloudy.ai/support"
|
|
67
|
+
}
|
|
68
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// Public presentation adapter. URLs contain public template locators only, never
|
|
2
|
+
// a connection credential, authorization token, goal text or identity claim.
|
|
3
|
+
export const CHOOSER_URL='https://kloudy.ai/api/customer/visual-chooser/start';
|
|
4
|
+
export const pendingChooserTool={name:'show_pending_chooser_link',description:'Show the pending Kloudy card and its HTTPS website fallback again. The website verifies account sign-in; the link is not authorization. This does not run a tool, model, installation or payment.',inputSchema:{type:'object',properties:{},additionalProperties:false},annotations:{readOnlyHint:true,destructiveHint:false,idempotentHint:true,openWorldHint:false}};
|
|
5
|
+
export function chooserResponse(result,{apps=false,goal}={}){
|
|
6
|
+
if(!result||typeof result!=='object'||Array.isArray(result)||result.isError)return result;
|
|
7
|
+
const data=result.structuredContent;if(!data||typeof data!=='object'||Array.isArray(data))return result;
|
|
8
|
+
const option=typeof data.selectedOptionId==='string'&&/^[a-z0-9-]{1,80}$/.test(data.selectedOptionId)?data.selectedOptionId:null;
|
|
9
|
+
const set=typeof data.choiceSetId==='string'&&/^visual-[a-f0-9]{1,64}$/.test(data.choiceSetId)?data.choiceSetId:null;
|
|
10
|
+
const url=option&&set?CHOOSER_URL+'#choice='+encodeURIComponent(option)+'&set='+encodeURIComponent(set):CHOOSER_URL;
|
|
11
|
+
const chooser={url,linkIsAuthorization:false,identityFromEmail:false,accountBindingVerified:false,returnMethod:'existing-authenticated-website-project-manifest',automaticIdeReturnVerified:false,...(set?{publicChoiceSetId:set}:{}),...(option?{publicOptionId:option}:{}),...(goal?{request:goal}:{})};
|
|
12
|
+
const text='Website chooser: '+url+'\nOpen this HTTPS link if your host does not show the card. Complete account sign-in/2FA on the website before opening private project choices. Email is a lookup hint, not proof. The host controls card rendering, clickable links and browser launch. Account-bound automatic return is not established by this public template locator.';
|
|
13
|
+
return {...result,content:[...(Array.isArray(result.content)?result.content:[]),{type:'text',text}],structuredContent:{...data,chooser},...(apps?{_meta:{...result._meta,ui:{...result._meta?.ui,resourceUri:'ui://widget/kloudy-visual-setup-v1.html'}}}:{})};
|
|
14
|
+
}
|
|
15
|
+
export function pendingChooserResponse(pending){
|
|
16
|
+
return pending?structuredClone(pending):{content:[{type:'text',text:'No pending chooser is retained in this MCP process. Open '+CHOOSER_URL+' and sign in to recover your existing project. This link is not a bearer token or authorization.'}],structuredContent:{pending:false,chooser:{url:CHOOSER_URL,linkIsAuthorization:false,accountBindingVerified:false}}};
|
|
17
|
+
}
|
package/src/remote.mjs
CHANGED
|
@@ -7,6 +7,7 @@ import {StdioServerTransport} from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
|
7
7
|
import {ListToolsRequestSchema,CallToolRequestSchema,ListResourcesRequestSchema,ReadResourceRequestSchema,ListResourceTemplatesRequestSchema,ToolListChangedNotificationSchema,ResourceListChangedNotificationSchema} from '@modelcontextprotocol/sdk/types.js';
|
|
8
8
|
import {REMOTE} from './editor-install.mjs';
|
|
9
9
|
import {autoupdateEnabled} from './autoupdate.mjs';
|
|
10
|
+
import {chooserResponse,pendingChooserResponse,pendingChooserTool} from './chooser-link.mjs';
|
|
10
11
|
const transports=new WeakMap();
|
|
11
12
|
// This proxy can relay Apps rendering, but cannot service sampling, roots or elicitation.
|
|
12
13
|
export function forwardedCapabilities(value={}){
|
|
@@ -28,7 +29,7 @@ export async function askRemote(question,options){
|
|
|
28
29
|
}
|
|
29
30
|
export async function serveRemote(options={}){
|
|
30
31
|
const connect=options.connect??connectRemote,enabled=autoupdateEnabled(options.autoupdate??process.env.KLOUDY_MCP_AUTOUPDATE);
|
|
31
|
-
let remote=await connect({...options,capabilities:{}}),ready=Promise.resolve(),closed=false,reconnecting;
|
|
32
|
+
let remote=await connect({...options,capabilities:{}}),ready=Promise.resolve(),closed=false,reconnecting,pendingChooser,requestGoal;
|
|
32
33
|
const upstream=remote.getServerCapabilities(),capabilities={};
|
|
33
34
|
if(upstream.tools)capabilities.tools=enabled&&upstream.tools.listChanged?{listChanged:true}:{};
|
|
34
35
|
if(upstream.resources)capabilities.resources=enabled&&upstream.resources.listChanged?{listChanged:true}:{};
|
|
@@ -54,7 +55,22 @@ export async function serveRemote(options={}){
|
|
|
54
55
|
return run(remote);
|
|
55
56
|
}
|
|
56
57
|
};
|
|
57
|
-
if(capabilities.tools){
|
|
58
|
+
if(capabilities.tools){
|
|
59
|
+
server.setRequestHandler(ListToolsRequestSchema,async req=>{
|
|
60
|
+
const result=await invoke('listTools',req.params);
|
|
61
|
+
return {...result,tools:[...result.tools.map(tool=>tool.name==='show_visual_setup_choices'?{...tool,inputSchema:{...tool.inputSchema,properties:{...tool.inputSchema.properties,goal:{type:'string',minLength:1,maxLength:1000,description:'Presentation request retained in this MCP process; never sent as a credential or URL.'}}}}:tool),...(result.tools.some(t=>t.name===pendingChooserTool.name)?[]:[pendingChooserTool])]};
|
|
62
|
+
});
|
|
63
|
+
server.setRequestHandler(CallToolRequestSchema,async req=>{
|
|
64
|
+
if(req.params.name===pendingChooserTool.name){if(Object.keys(req.params.arguments||{}).length)throw Error('Pending chooser lookup takes no identity or credential fields');return pendingChooserResponse(pendingChooser);}
|
|
65
|
+
if(req.params.name!=='show_visual_setup_choices')return invoke('callTool',req.params);
|
|
66
|
+
const argumentsValue={...(req.params.arguments||{})};
|
|
67
|
+
let nextGoal=requestGoal;
|
|
68
|
+
if(Object.hasOwn(argumentsValue,'goal')){if(typeof argumentsValue.goal!=='string'||!argumentsValue.goal.trim()||argumentsValue.goal.length>1000)throw Error('Use a presentation request of 1-1000 characters');nextGoal=argumentsValue.goal;delete argumentsValue.goal;}
|
|
69
|
+
const result=await invoke('callTool',{...req.params,arguments:argumentsValue});
|
|
70
|
+
const decorated=chooserResponse(result,{apps:!!forwardedCapabilities(server.getClientCapabilities()).experimental,goal:nextGoal});
|
|
71
|
+
if(!decorated.isError){requestGoal=nextGoal;pendingChooser=decorated;}return decorated;
|
|
72
|
+
});
|
|
73
|
+
}
|
|
58
74
|
// Resource delivery is independent of notification/autoupdate opt-in.
|
|
59
75
|
if(capabilities.resources){
|
|
60
76
|
server.setRequestHandler(ListResourcesRequestSchema,req=>invoke('listResources',req.params));
|