wxo-builder-mcp-server 1.0.8

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.
@@ -0,0 +1,191 @@
1
+ /**
2
+ * WxO MCP Server - Connections & Connectors API
3
+ * Mirrors vscode-extension/api/connections.ts
4
+ *
5
+ * @author Markus van Kempen
6
+ * @license Apache-2.0
7
+ */
8
+ import { woFetch } from './auth.js';
9
+ /** List available connectors from the catalog. */
10
+ export async function listConnectors(limit = 50) {
11
+ const response = await woFetch(`/v1/orchestrate/catalog/applications?limit=${limit}`, {
12
+ method: 'GET',
13
+ });
14
+ if (!response.ok) {
15
+ const text = await response.text();
16
+ throw new Error(`Failed to list connectors: ${response.status} ${text}`);
17
+ }
18
+ return await response.json();
19
+ }
20
+ /** List connections (configured + unconfigured) for a scope. */
21
+ export async function listConnections(scope) {
22
+ const scopeParam = scope || 'draft';
23
+ const response = await woFetch(`/v1/orchestrate/connections/applications?include_details=true&scope=${scopeParam}`, { method: 'GET' });
24
+ if (!response.ok) {
25
+ const text = await response.text();
26
+ console.error(`Connections API: ${response.status} - ${text}`);
27
+ return { applications: [] };
28
+ }
29
+ return await response.json();
30
+ }
31
+ /**
32
+ * List only active and live connections (not tools). Returns deduplicated connection names.
33
+ * Use for "list all connections which are active and live, just the connections not the tools".
34
+ */
35
+ export async function listActiveLiveConnections() {
36
+ const res = await listConnections('live');
37
+ const apps = res?.applications || [];
38
+ const active = apps.filter((a) => a.credentials_entered === true);
39
+ const seen = new Set();
40
+ const connections = [];
41
+ for (const a of active) {
42
+ const appId = a.app_id || a.connection_id || '';
43
+ if (!appId || seen.has(appId))
44
+ continue;
45
+ seen.add(appId);
46
+ connections.push({
47
+ app_id: appId,
48
+ display_name: a.display_name || a.name || appId,
49
+ });
50
+ }
51
+ return {
52
+ connections,
53
+ names: connections.map((c) => c.display_name || c.app_id),
54
+ };
55
+ }
56
+ /** List connections from both draft and live scopes. */
57
+ export async function listConnectionsAll() {
58
+ const draftRes = await listConnections('draft');
59
+ const draftApps = draftRes?.applications || [];
60
+ let liveApps = [];
61
+ try {
62
+ const liveRes = await listConnections('live');
63
+ liveApps = liveRes?.applications || [];
64
+ }
65
+ catch {
66
+ // Developer Edition may not have live scope
67
+ }
68
+ const merged = [...draftApps];
69
+ const seen = new Set(draftApps.map((a) => `${a.app_id || a.connection_id}:${a.environment || 'draft'}`));
70
+ for (const a of liveApps) {
71
+ const key = `${a.app_id || a.connection_id}:${a.environment || 'live'}`;
72
+ if (!seen.has(key)) {
73
+ seen.add(key);
74
+ merged.push(a);
75
+ }
76
+ }
77
+ return { applications: merged };
78
+ }
79
+ /** Get a connection by app_id. */
80
+ export async function getConnection(appId) {
81
+ const response = await woFetch(`/v1/orchestrate/connections/applications?app_id=${encodeURIComponent(appId)}`, {
82
+ method: 'GET',
83
+ });
84
+ if (!response.ok) {
85
+ const text = await response.text();
86
+ throw new Error(`Failed to get connection: ${response.status} ${text}`);
87
+ }
88
+ return await response.json();
89
+ }
90
+ /** Create a new connection entry. */
91
+ export async function createConnection(payload) {
92
+ const response = await woFetch('/v1/orchestrate/connections/applications', {
93
+ method: 'POST',
94
+ body: JSON.stringify(payload),
95
+ });
96
+ if (!response.ok) {
97
+ const text = await response.text();
98
+ throw new Error(`Failed to create connection: ${response.status} ${text}`);
99
+ }
100
+ return await response.json();
101
+ }
102
+ /** Delete a connection by app_id. */
103
+ export async function deleteConnection(appId) {
104
+ const response = await woFetch(`/v1/orchestrate/connections/applications/${encodeURIComponent(appId)}`, {
105
+ method: 'DELETE',
106
+ });
107
+ if (!response.ok) {
108
+ const text = await response.text();
109
+ throw new Error(`Failed to delete connection: ${response.status} ${text}`);
110
+ }
111
+ return { success: true };
112
+ }
113
+ /** Create connection configuration. */
114
+ export async function createConnectionConfiguration(appId, env, kind, type = 'team', serverUrl) {
115
+ const securityScheme = kind === 'api_key'
116
+ ? 'api_key_auth'
117
+ : kind === 'basic'
118
+ ? 'basic_auth'
119
+ : kind === 'bearer'
120
+ ? 'bearer_auth'
121
+ : 'api_key_auth';
122
+ const body = {
123
+ environment: env,
124
+ kind,
125
+ type,
126
+ preference: type,
127
+ security_scheme: securityScheme,
128
+ };
129
+ if (serverUrl)
130
+ body.server_url = serverUrl;
131
+ const response = await woFetch(`/v1/orchestrate/connections/applications/${encodeURIComponent(appId)}/configurations`, { method: 'POST', body: JSON.stringify(body) });
132
+ if (!response.ok) {
133
+ const text = await response.text();
134
+ throw new Error(`Failed to create configuration: ${response.status} ${text}`);
135
+ }
136
+ return await response.json().catch(() => ({ success: true }));
137
+ }
138
+ /** Set API key credentials. */
139
+ export async function setApiKeyCredentials(appId, apiKey, env = 'draft') {
140
+ let response = await woFetch(`/v1/orchestrate/connections/applications/${encodeURIComponent(appId)}/configs/${env}/runtime_credentials`, {
141
+ method: 'PATCH',
142
+ body: JSON.stringify({ runtime_credentials: { api_key: apiKey } }),
143
+ });
144
+ if (!response.ok) {
145
+ response = await woFetch(`/v1/orchestrate/connections/applications/${encodeURIComponent(appId)}/configs/${env}/runtime_credentials`, {
146
+ method: 'POST',
147
+ body: JSON.stringify({ runtime_credentials: { api_key: apiKey } }),
148
+ });
149
+ if (!response.ok) {
150
+ const text = await response.text();
151
+ throw new Error(`Failed to set API key credentials: ${response.status} ${text}`);
152
+ }
153
+ }
154
+ return await response.json().catch(() => ({ success: true }));
155
+ }
156
+ /** Set basic-auth credentials. */
157
+ export async function setBasicCredentials(appId, username, password, env = 'draft') {
158
+ let response = await woFetch(`/v1/orchestrate/connections/applications/${encodeURIComponent(appId)}/configs/${env}/runtime_credentials`, {
159
+ method: 'PATCH',
160
+ body: JSON.stringify({ runtime_credentials: { username, password } }),
161
+ });
162
+ if (!response.ok) {
163
+ response = await woFetch(`/v1/orchestrate/connections/applications/${encodeURIComponent(appId)}/configs/${env}/runtime_credentials`, {
164
+ method: 'POST',
165
+ body: JSON.stringify({ runtime_credentials: { username, password } }),
166
+ });
167
+ if (!response.ok) {
168
+ const text = await response.text();
169
+ throw new Error(`Failed to set basic credentials: ${response.status} ${text}`);
170
+ }
171
+ }
172
+ return await response.json().catch(() => ({ success: true }));
173
+ }
174
+ /** Set bearer token credentials. */
175
+ export async function setBearerCredentials(appId, token, env = 'draft') {
176
+ let response = await woFetch(`/v1/orchestrate/connections/applications/${encodeURIComponent(appId)}/configs/${env}/runtime_credentials`, {
177
+ method: 'PATCH',
178
+ body: JSON.stringify({ runtime_credentials: { token } }),
179
+ });
180
+ if (!response.ok) {
181
+ response = await woFetch(`/v1/orchestrate/connections/applications/${encodeURIComponent(appId)}/configs/${env}/runtime_credentials`, {
182
+ method: 'POST',
183
+ body: JSON.stringify({ runtime_credentials: { token } }),
184
+ });
185
+ if (!response.ok) {
186
+ const text = await response.text();
187
+ throw new Error(`Failed to set bearer credentials: ${response.status} ${text}`);
188
+ }
189
+ }
190
+ return await response.json().catch(() => ({ success: true }));
191
+ }
package/dist/flows.js ADDED
@@ -0,0 +1,73 @@
1
+ import { woFetch } from './auth.js';
2
+ /**
3
+ * List all available flows.
4
+ */
5
+ export async function listFlows(limit = 20, offset = 0) {
6
+ console.error(`Listing flows...`);
7
+ try {
8
+ const response = await woFetch(`/v1/flows/?limit=${limit}&offset=${offset}`, {
9
+ method: 'GET',
10
+ });
11
+ if (!response.ok) {
12
+ const text = await response.text();
13
+ throw new Error(`Failed to list flows: ${response.status} ${response.statusText} - ${text}`);
14
+ }
15
+ return await response.json();
16
+ }
17
+ catch (e) {
18
+ throw new Error(`API Request Failed: ${e.message}`);
19
+ }
20
+ }
21
+ /**
22
+ * Get a specific flow by ID.
23
+ */
24
+ export async function getFlow(flowId) {
25
+ console.error(`Getting flow ${flowId}...`);
26
+ try {
27
+ const response = await woFetch(`/v1/flows/${flowId}`, { method: 'GET' });
28
+ if (!response.ok) {
29
+ throw new Error(`Failed to get flow: ${response.status} ${response.statusText}`);
30
+ }
31
+ return await response.json();
32
+ }
33
+ catch (e) {
34
+ throw new Error(`API Request Failed: ${e.message}`);
35
+ }
36
+ }
37
+ /**
38
+ * Delete a flow by ID.
39
+ */
40
+ export async function deleteFlow(flowId) {
41
+ console.error(`Deleting flow ${flowId}...`);
42
+ try {
43
+ const response = await woFetch(`/v1/flows/${flowId}`, { method: 'DELETE' });
44
+ if (!response.ok) {
45
+ throw new Error(`Failed to delete flow: ${response.status} ${response.statusText}`);
46
+ }
47
+ return { success: true, message: `Flow ${flowId} deleted successfully.` };
48
+ }
49
+ catch (e) {
50
+ throw new Error(`API Request Failed: ${e.message}`);
51
+ }
52
+ }
53
+ /**
54
+ * Create or Update a Flow.
55
+ * The API seems to just take the Flow JSON.
56
+ */
57
+ export async function createFlow(flowJson) {
58
+ console.error(`Creating flow...`);
59
+ try {
60
+ const response = await woFetch('/v1/flows/', {
61
+ method: 'POST',
62
+ body: JSON.stringify(flowJson),
63
+ });
64
+ if (!response.ok) {
65
+ const text = await response.text();
66
+ throw new Error(`Failed to create flow: ${response.status} ${response.statusText} - ${text}`);
67
+ }
68
+ return await response.json();
69
+ }
70
+ catch (e) {
71
+ throw new Error(`API Request Failed: ${e.message}`);
72
+ }
73
+ }