@descix/cli 1.0.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/README.md +95 -0
- package/SERVICE_README_sdk.md +399 -0
- package/agent-assets/guides/README.md +61 -0
- package/agent-assets/guides/dynamic-site-pattern.md +125 -0
- package/agent-assets/guides/knowledge-only-pattern.md +93 -0
- package/agent-assets/guides/microservice-pattern.md +152 -0
- package/agent-assets/guides/static-site-pattern.md +111 -0
- package/agent-assets/instructions/app-asset-validation.md +477 -0
- package/agent-assets/instructions/onboarding-flow.md +408 -0
- package/agent-assets/instructions/standard-folder-structure.md +125 -0
- package/agent-assets/reference/app-creation.md +381 -0
- package/agent-assets/reference/architecture.md +406 -0
- package/agent-assets/reference/local-dev.md +138 -0
- package/agent-assets/reference/mcp-integration.md +424 -0
- package/agent-assets/reference/workspace-config.md +415 -0
- package/agent-assets/rules/descix_mcp.template.mdc +243 -0
- package/bin/descix.js +3930 -0
- package/bin/mcp-server.js +382 -0
- package/descix-cli-1.0.0.tgz +0 -0
- package/lib/agent-files.js +162 -0
- package/lib/api-client.js +458 -0
- package/lib/auth-guard.js +67 -0
- package/lib/commands/app-wizard.js +627 -0
- package/lib/commands/auth.js +407 -0
- package/lib/commands/buy.js +207 -0
- package/lib/commands/clone.js +91 -0
- package/lib/commands/config.js +155 -0
- package/lib/commands/doctor.js +277 -0
- package/lib/commands/folder.js +291 -0
- package/lib/commands/init.js +257 -0
- package/lib/commands/kb.js +654 -0
- package/lib/commands/mcp.js +273 -0
- package/lib/commands/serve.js +12 -0
- package/lib/commands/status.js +239 -0
- package/lib/commands/update.js +653 -0
- package/lib/core/Chunker.js +610 -0
- package/lib/core/Hydrator.js +801 -0
- package/lib/core/PathContext.js +335 -0
- package/lib/core/Syncer.js +310 -0
- package/lib/core/index.js +32 -0
- package/lib/global-config.js +86 -0
- package/lib/google-storage-adc.js +511 -0
- package/lib/wallet-file.js +232 -0
- package/lib/wizard/setup.js +502 -0
- package/lib/workspace-config.js +712 -0
- package/lib/workspace-utils.js +126 -0
- package/package.json +41 -0
- package/templates/agent-claude.md +226 -0
- package/templates/agent-cline.md +133 -0
- package/templates/agent-copilot.md +133 -0
- package/templates/agent-cursor.md +133 -0
- package/templates/descix_mcp.mdc +122 -0
- package/templates/drive/README.md +42 -0
- package/templates/drive/app/assets/app_description.md +13 -0
- package/templates/drive/app/assets/icon.png +0 -0
- package/templates/drive/app/assets/system_instructions.md +17 -0
- package/templates/drive/app/kb/General/README.md +25 -0
- package/templates/drive/community/Apps/.gitkeep +4 -0
- package/templates/drive/community/community_assets/community_description.md +15 -0
- package/templates/drive/community/community_assets/icon.png +0 -0
- package/templates/drive_templates/README.md +104 -0
- package/templates/drive_templates/agent_app_template/assets/app_description.txt +13 -0
- package/templates/drive_templates/agent_app_template/assets/system_instructions.txt +17 -0
- package/templates/drive_templates/agent_app_template/kb/General/README.md +25 -0
- package/templates/drive_templates/agent_app_template/microservice/.gitkeep +10 -0
- package/templates/drive_templates/agent_app_template/site/.gitkeep +4 -0
- package/templates/drive_templates/community_template/Apps/.gitkeep +4 -0
- package/templates/drive_templates/community_template/community_assets/community_description.txt +15 -0
- package/templates/scaffolds/README.md +62 -0
- package/templates/scaffolds/microservice/Dockerfile +19 -0
- package/templates/scaffolds/microservice/SERVICE_README_sdk.md +399 -0
- package/templates/scaffolds/microservice/app.js +50 -0
- package/templates/scaffolds/microservice/app.yaml +8 -0
- package/templates/scaffolds/microservice/defaults-config.json +5 -0
- package/templates/scaffolds/microservice/dev-overrides.json.example +5 -0
- package/templates/scaffolds/microservice/manifest.json +49 -0
- package/templates/scaffolds/microservice/package-lock.json +2645 -0
- package/templates/scaffolds/microservice/package.json +29 -0
- package/templates/scaffolds/microservice/scripts/register.js +55 -0
- package/templates/scaffolds/microservice/services/apiFront.js +75 -0
- package/templates/scaffolds/microservice/services/commandHandlers/sampleCommands.js +57 -0
- package/templates/scaffolds/microservice/services/mcpClient.js +78 -0
- package/templates/scaffolds/microservice/services/utils.js +247 -0
- package/templates/scaffolds/microservice/setup-schema.json +18 -0
- package/templates/scaffolds/microservice/templates/SERVICE_README_TEMPLATE.md +143 -0
- package/templates/scaffolds/site/DeSciXAppSDK.js +62 -0
- package/templates/scaffolds/site/README.md +51 -0
- package/templates/scaffolds/site/app.js +22 -0
- package/templates/scaffolds/site/index.html +42 -0
- package/templates/scaffolds/site/styles.css +123 -0
- package/test-hydration.js +150 -0
- package/vendor/mcp/transports/http-sse-transport.js +196 -0
- package/vendor/mcp/transports/index.js +15 -0
- package/vendor/mcp/transports/stdio-transport.js +118 -0
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTTP+SSE Transport for MCP Server
|
|
3
|
+
*
|
|
4
|
+
* Handles JSON-RPC 2.0 over HTTP POST with SSE for streaming
|
|
5
|
+
* Used by remote MCP clients like ChatGPT, web-based agents
|
|
6
|
+
*
|
|
7
|
+
* Authentication: X-DeSciX-Signature header (wallet signature as API key)
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { User } from '../../../descix-cli/lib/api-client.js';
|
|
11
|
+
|
|
12
|
+
export class HttpSseTransport {
|
|
13
|
+
constructor(mcpServer, options = {}) {
|
|
14
|
+
this.mcpServer = mcpServer;
|
|
15
|
+
this.options = options;
|
|
16
|
+
this.apiClient = options.apiClient || null;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Create Express middleware for MCP HTTP endpoint
|
|
21
|
+
* @returns {Function} Express middleware
|
|
22
|
+
*/
|
|
23
|
+
createMiddleware() {
|
|
24
|
+
return async (req, res, next) => {
|
|
25
|
+
// Handle MCP JSON-RPC requests
|
|
26
|
+
if (req.method !== 'POST') {
|
|
27
|
+
return res.status(405).json({
|
|
28
|
+
jsonrpc: '2.0',
|
|
29
|
+
id: null,
|
|
30
|
+
error: { code: -32600, message: 'Only POST requests are supported' }
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
try {
|
|
35
|
+
// Extract and validate signature-based auth
|
|
36
|
+
const signature = this.extractSignature(req);
|
|
37
|
+
let walletInfo = null;
|
|
38
|
+
let user = null;
|
|
39
|
+
|
|
40
|
+
if (signature) {
|
|
41
|
+
// Authenticate via API signature (O(1) lookup)
|
|
42
|
+
const authResult = await this.authenticateBySignature(signature);
|
|
43
|
+
if (authResult) {
|
|
44
|
+
user = authResult.user;
|
|
45
|
+
walletInfo = {
|
|
46
|
+
userId: user.id,
|
|
47
|
+
walletAddress: user.wallet_address,
|
|
48
|
+
signatureId: authResult.signatureRecord.id,
|
|
49
|
+
permissions: authResult.signatureRecord.permissions,
|
|
50
|
+
communities: authResult.signatureRecord.communities
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Handle the MCP request
|
|
56
|
+
const request = req.body;
|
|
57
|
+
const response = await this.mcpServer.handleRequest(request, user, walletInfo);
|
|
58
|
+
|
|
59
|
+
// Only send response if it's not a notification
|
|
60
|
+
if (response !== null) {
|
|
61
|
+
res.json(response);
|
|
62
|
+
} else {
|
|
63
|
+
res.status(204).end();
|
|
64
|
+
}
|
|
65
|
+
} catch (error) {
|
|
66
|
+
console.error('[MCP:HTTP] Error handling request:', error.message);
|
|
67
|
+
res.status(500).json({
|
|
68
|
+
jsonrpc: '2.0',
|
|
69
|
+
id: req.body?.id || null,
|
|
70
|
+
error: {
|
|
71
|
+
code: -32603,
|
|
72
|
+
message: 'Internal error',
|
|
73
|
+
data: error.message
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Create SSE endpoint for streaming responses
|
|
82
|
+
* @returns {Function} Express middleware for SSE
|
|
83
|
+
*/
|
|
84
|
+
createSseMiddleware() {
|
|
85
|
+
return async (req, res, next) => {
|
|
86
|
+
// Set SSE headers
|
|
87
|
+
res.setHeader('Content-Type', 'text/event-stream');
|
|
88
|
+
res.setHeader('Cache-Control', 'no-cache');
|
|
89
|
+
res.setHeader('Connection', 'keep-alive');
|
|
90
|
+
res.setHeader('X-Accel-Buffering', 'no');
|
|
91
|
+
|
|
92
|
+
// Extract signature for auth
|
|
93
|
+
const signature = this.extractSignature(req);
|
|
94
|
+
let walletInfo = null;
|
|
95
|
+
|
|
96
|
+
if (signature) {
|
|
97
|
+
const authResult = await this.authenticateBySignature(signature);
|
|
98
|
+
if (authResult) {
|
|
99
|
+
walletInfo = {
|
|
100
|
+
userId: authResult.user.id,
|
|
101
|
+
walletAddress: authResult.user.wallet_address,
|
|
102
|
+
signatureId: authResult.signatureRecord.id,
|
|
103
|
+
permissions: authResult.signatureRecord.permissions
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Send initial connection event
|
|
109
|
+
res.write(`event: connected\ndata: ${JSON.stringify({ status: 'connected' })}\n\n`);
|
|
110
|
+
|
|
111
|
+
// Store connection info for potential use
|
|
112
|
+
req.mcpConnection = {
|
|
113
|
+
walletInfo,
|
|
114
|
+
sendEvent: (event, data) => {
|
|
115
|
+
res.write(`event: ${event}\ndata: ${JSON.stringify(data)}\n\n`);
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
// Handle client disconnect
|
|
120
|
+
req.on('close', () => {
|
|
121
|
+
console.error('[MCP:SSE] Client disconnected');
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
// Keep connection alive with heartbeat
|
|
125
|
+
const heartbeat = setInterval(() => {
|
|
126
|
+
res.write(`: heartbeat\n\n`);
|
|
127
|
+
}, 30000);
|
|
128
|
+
|
|
129
|
+
req.on('close', () => {
|
|
130
|
+
clearInterval(heartbeat);
|
|
131
|
+
});
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Extract signature from request
|
|
137
|
+
* Supports header: X-DeSciX-Signature or Authorization: Bearer <signature>
|
|
138
|
+
*/
|
|
139
|
+
extractSignature(req) {
|
|
140
|
+
// Check X-DeSciX-Signature header
|
|
141
|
+
const sigHeader = req.headers['x-descix-signature'];
|
|
142
|
+
if (sigHeader) return sigHeader;
|
|
143
|
+
|
|
144
|
+
// Check Authorization header
|
|
145
|
+
const authHeader = req.headers['authorization'];
|
|
146
|
+
if (authHeader && authHeader.startsWith('Signature ')) {
|
|
147
|
+
return authHeader.substring(10);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// Check query param (for SSE)
|
|
151
|
+
if (req.query?.signature) {
|
|
152
|
+
return req.query.signature;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
return null;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Authenticate by signature via /apifront/
|
|
160
|
+
* @param {string} signature - Wallet signature
|
|
161
|
+
* @returns {Promise<{user, signatureRecord}|null>}
|
|
162
|
+
*/
|
|
163
|
+
async authenticateBySignature(signature) {
|
|
164
|
+
if (!this.apiClient) {
|
|
165
|
+
console.error('[MCP:HTTP] No API client configured for signature auth');
|
|
166
|
+
return null;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
try {
|
|
170
|
+
const result = await this.apiClient.invoke('authenticate_by_signature', {
|
|
171
|
+
signature
|
|
172
|
+
}, { allowGuest: true });
|
|
173
|
+
|
|
174
|
+
if (result?.success) {
|
|
175
|
+
return {
|
|
176
|
+
user: { id: result.user_id },
|
|
177
|
+
signatureRecord: {
|
|
178
|
+
id: result.signature_id,
|
|
179
|
+
name: result.signature_name,
|
|
180
|
+
permissions: result.permissions,
|
|
181
|
+
communities: result.communities
|
|
182
|
+
}
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
} catch (error) {
|
|
186
|
+
console.error('[MCP:HTTP] Signature auth failed:', error.message);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
return null;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
export default HttpSseTransport;
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Transport Layer
|
|
3
|
+
*
|
|
4
|
+
* Provides pluggable transport implementations for the DeSciX MCP Server:
|
|
5
|
+
* - StdioTransport: For CLI-based clients (Cursor, VS Code, Claude Desktop)
|
|
6
|
+
* - HttpSseTransport: For remote HTTP clients (ChatGPT, web agents)
|
|
7
|
+
*
|
|
8
|
+
* All transports use the same DeSciXMCPServer core with HTTP-only API calls.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
export { StdioTransport } from './stdio-transport.js';
|
|
12
|
+
export { HttpSseTransport } from './http-sse-transport.js';
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stdio Transport for MCP Server
|
|
3
|
+
*
|
|
4
|
+
* Uses the official @modelcontextprotocol/sdk for proper protocol handling.
|
|
5
|
+
* This wrapper bridges our DeSciXMCPServer with the official SDK's transport.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* StdioTransport - bridges DeSciXMCPServer to official MCP SDK transport
|
|
12
|
+
*
|
|
13
|
+
* Note: This is a thin wrapper. The actual MCP server should use the
|
|
14
|
+
* official Server class from @modelcontextprotocol/sdk for full compatibility.
|
|
15
|
+
*/
|
|
16
|
+
export class StdioTransport {
|
|
17
|
+
constructor(mcpServer, options = {}) {
|
|
18
|
+
this.mcpServer = mcpServer;
|
|
19
|
+
this.options = options;
|
|
20
|
+
this.walletInfo = options.walletInfo || null;
|
|
21
|
+
this.transport = null;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Start the stdio transport using official SDK
|
|
26
|
+
*/
|
|
27
|
+
async start() {
|
|
28
|
+
console.error('[MCP:Stdio] Starting with official MCP SDK transport...');
|
|
29
|
+
|
|
30
|
+
// Create the official stdio transport
|
|
31
|
+
this.transport = new StdioServerTransport();
|
|
32
|
+
|
|
33
|
+
// The transport handles the protocol - we need to connect it to our server
|
|
34
|
+
// This is a temporary bridge until we fully migrate to the SDK's Server class
|
|
35
|
+
console.error('[MCP:Stdio] Transport created, delegating to MCP server...');
|
|
36
|
+
|
|
37
|
+
// For now, we'll use manual message handling since our server has custom logic
|
|
38
|
+
// The official SDK uses a different architecture (Server class with handlers)
|
|
39
|
+
|
|
40
|
+
// Import readline for manual handling until full SDK migration
|
|
41
|
+
const readline = await import('readline');
|
|
42
|
+
|
|
43
|
+
const rl = readline.createInterface({
|
|
44
|
+
input: process.stdin,
|
|
45
|
+
terminal: false
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
console.error('[MCP:Stdio] Transport ready, waiting for JSON-RPC requests...');
|
|
49
|
+
|
|
50
|
+
rl.on('line', async (line) => {
|
|
51
|
+
if (!line.trim()) return;
|
|
52
|
+
|
|
53
|
+
try {
|
|
54
|
+
const request = JSON.parse(line);
|
|
55
|
+
console.error(`[MCP:Stdio] << ${request.method || 'unknown'} (id: ${request.id})`);
|
|
56
|
+
|
|
57
|
+
const response = await this.mcpServer.handleRequest(request, null, this.walletInfo);
|
|
58
|
+
|
|
59
|
+
if (response !== null) {
|
|
60
|
+
const json = JSON.stringify(response);
|
|
61
|
+
console.error(`[MCP:Stdio] >> Response (id: ${response.id}, ${json.length} bytes)`);
|
|
62
|
+
// Write to stdout with explicit flush
|
|
63
|
+
process.stdout.write(json + '\n', () => {
|
|
64
|
+
// Callback after write completes
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
} catch (error) {
|
|
68
|
+
console.error('[MCP:Stdio] Parse error:', error.message);
|
|
69
|
+
const errorResponse = {
|
|
70
|
+
jsonrpc: '2.0',
|
|
71
|
+
id: null,
|
|
72
|
+
error: {
|
|
73
|
+
code: -32700,
|
|
74
|
+
message: 'Parse error',
|
|
75
|
+
data: error.message
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
process.stdout.write(JSON.stringify(errorResponse) + '\n');
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
rl.on('close', () => {
|
|
83
|
+
console.error('[MCP:Stdio] Transport closed');
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
// Keep process alive
|
|
87
|
+
return new Promise((resolve) => {
|
|
88
|
+
rl.on('close', resolve);
|
|
89
|
+
process.on('SIGINT', () => {
|
|
90
|
+
rl.close();
|
|
91
|
+
resolve();
|
|
92
|
+
});
|
|
93
|
+
process.on('SIGTERM', () => {
|
|
94
|
+
rl.close();
|
|
95
|
+
resolve();
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Stop the transport
|
|
102
|
+
*/
|
|
103
|
+
stop() {
|
|
104
|
+
console.error('[MCP:Stdio] Transport stopped');
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Update wallet info
|
|
109
|
+
*/
|
|
110
|
+
setWalletInfo(walletInfo) {
|
|
111
|
+
this.walletInfo = walletInfo;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export default StdioTransport;
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
|