@aerostack/openclaw-bridge 0.1.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 +146 -0
- package/dist/index.d.ts +24 -0
- package/dist/index.js +265 -0
- package/dist/index.js.map +1 -0
- package/package.json +38 -0
package/README.md
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
# @aerostack/openclaw-bridge
|
|
2
|
+
|
|
3
|
+
Connect [OpenClaw](https://openclaw.ai) to any [Aerostack Workspace](https://aerostack.dev) — one URL, all your MCP tools, with built-in security.
|
|
4
|
+
|
|
5
|
+
[](https://opensource.org/licenses/MIT)
|
|
6
|
+
[](https://www.npmjs.com/package/@aerostack/openclaw-bridge)
|
|
7
|
+
|
|
8
|
+
## Why?
|
|
9
|
+
|
|
10
|
+
OpenClaw only supports **stdio** MCP servers. Aerostack Workspaces use **HTTP**. This bridge connects them — no code required.
|
|
11
|
+
|
|
12
|
+
Instead of configuring 50 separate MCP servers in OpenClaw, point at one Aerostack Workspace and get:
|
|
13
|
+
|
|
14
|
+
- **All tools in one place** — composed from multiple MCP servers
|
|
15
|
+
- **Centralized OAuth** — 27+ providers managed by Aerostack, not your agent
|
|
16
|
+
- **Human approval gates** — sensitive tools require workspace owner approval before executing
|
|
17
|
+
- **Per-tool permissions** — workspace tokens scope exactly which tools are accessible
|
|
18
|
+
- **Usage tracking & audit** — every tool call logged and metered
|
|
19
|
+
- **Rate limiting** — per-token, plan-tiered
|
|
20
|
+
|
|
21
|
+
## Quick Start
|
|
22
|
+
|
|
23
|
+
### 1. Get a workspace token
|
|
24
|
+
|
|
25
|
+
In your [Aerostack Admin Dashboard](https://app.aerostack.dev), go to your workspace settings and generate a token (`mwt_...`).
|
|
26
|
+
|
|
27
|
+
### 2. Configure OpenClaw
|
|
28
|
+
|
|
29
|
+
Add to your OpenClaw config (`openclaw.json` or via `openclaw mcp set`):
|
|
30
|
+
|
|
31
|
+
```json
|
|
32
|
+
{
|
|
33
|
+
"mcp": {
|
|
34
|
+
"servers": {
|
|
35
|
+
"my-workspace": {
|
|
36
|
+
"command": "npx",
|
|
37
|
+
"args": ["-y", "@aerostack/openclaw-bridge"],
|
|
38
|
+
"env": {
|
|
39
|
+
"AEROSTACK_WORKSPACE_URL": "https://api.aerostack.dev/api/gateway/ws/my-workspace",
|
|
40
|
+
"AEROSTACK_TOKEN": "mwt_your_token_here"
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Or via CLI:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
openclaw mcp set my-workspace '{
|
|
52
|
+
"command": "npx",
|
|
53
|
+
"args": ["-y", "@aerostack/openclaw-bridge"],
|
|
54
|
+
"env": {
|
|
55
|
+
"AEROSTACK_WORKSPACE_URL": "https://api.aerostack.dev/api/gateway/ws/my-workspace",
|
|
56
|
+
"AEROSTACK_TOKEN": "mwt_your_token_here"
|
|
57
|
+
}
|
|
58
|
+
}'
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### 3. Use it
|
|
62
|
+
|
|
63
|
+
```
|
|
64
|
+
You: Search GitHub for open issues in my repo
|
|
65
|
+
OpenClaw: [calls github__search_issues via Aerostack workspace]
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Tools are namespaced as `{server}__{tool}` (e.g., `github__create_issue`, `slack__send_message`).
|
|
69
|
+
|
|
70
|
+
## How It Works
|
|
71
|
+
|
|
72
|
+
```
|
|
73
|
+
OpenClaw (stdio) → Bridge (this package) → HTTPS → Aerostack Workspace Gateway
|
|
74
|
+
↓
|
|
75
|
+
┌─────────────────────────┐
|
|
76
|
+
│ Fan-out to MCP servers │
|
|
77
|
+
│ GitHub, Slack, Gmail, │
|
|
78
|
+
│ custom Workers, etc. │
|
|
79
|
+
└─────────────────────────┘
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
The bridge:
|
|
83
|
+
|
|
84
|
+
1. Starts as a stdio MCP server (what OpenClaw expects)
|
|
85
|
+
2. Forwards all JSON-RPC requests to your workspace over HTTPS
|
|
86
|
+
3. Handles SSE streaming responses transparently
|
|
87
|
+
4. Manages the approval gate flow automatically
|
|
88
|
+
|
|
89
|
+
## Approval Gates
|
|
90
|
+
|
|
91
|
+
When a workspace owner configures approval requirements on sensitive tools, the bridge handles it transparently:
|
|
92
|
+
|
|
93
|
+
```
|
|
94
|
+
OpenClaw calls dangerous_tool
|
|
95
|
+
→ Bridge forwards to workspace
|
|
96
|
+
→ Workspace returns "needs approval" (-32050)
|
|
97
|
+
→ Bridge polls for approval status (logs to stderr)
|
|
98
|
+
→ Workspace owner approves/rejects in admin dashboard
|
|
99
|
+
→ Bridge retries on approval, returns error on rejection
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Your OpenClaw agent sees either a successful result or a clear error — no special handling needed.
|
|
103
|
+
|
|
104
|
+
## Configuration
|
|
105
|
+
|
|
106
|
+
All configuration is via environment variables:
|
|
107
|
+
|
|
108
|
+
| Variable | Required | Default | Description |
|
|
109
|
+
|----------|----------|---------|-------------|
|
|
110
|
+
| `AEROSTACK_WORKSPACE_URL` | Yes | — | Full workspace endpoint URL |
|
|
111
|
+
| `AEROSTACK_TOKEN` | Yes | — | Workspace token (`mwt_...`) |
|
|
112
|
+
| `AEROSTACK_APPROVAL_POLL_MS` | No | `3000` | Approval polling interval (ms) |
|
|
113
|
+
| `AEROSTACK_APPROVAL_TIMEOUT_MS` | No | `300000` | Max approval wait time (5 min) |
|
|
114
|
+
| `AEROSTACK_REQUEST_TIMEOUT_MS` | No | `30000` | HTTP request timeout (30s) |
|
|
115
|
+
|
|
116
|
+
## Supported MCP Methods
|
|
117
|
+
|
|
118
|
+
| Method | Description |
|
|
119
|
+
|--------|-------------|
|
|
120
|
+
| `tools/list` | List all tools from all workspace servers |
|
|
121
|
+
| `tools/call` | Call a namespaced tool (with approval handling) |
|
|
122
|
+
| `resources/list` | List resources from all workspace servers |
|
|
123
|
+
| `resources/read` | Read a specific resource |
|
|
124
|
+
| `prompts/list` | List prompts from all workspace servers |
|
|
125
|
+
| `prompts/get` | Get a prompt with arguments |
|
|
126
|
+
|
|
127
|
+
## Works With Any stdio MCP Client
|
|
128
|
+
|
|
129
|
+
While built for OpenClaw, this bridge works with **any MCP client that supports stdio transport** — Claude Desktop, Cursor, Windsurf, or custom integrations.
|
|
130
|
+
|
|
131
|
+
## Requirements
|
|
132
|
+
|
|
133
|
+
- Node.js 18+
|
|
134
|
+
- An Aerostack account with a configured workspace
|
|
135
|
+
- A workspace token with appropriate tool permissions
|
|
136
|
+
|
|
137
|
+
## Links
|
|
138
|
+
|
|
139
|
+
- [Aerostack Docs](https://docs.aerostack.dev)
|
|
140
|
+
- [Aerostack Admin](https://app.aerostack.dev)
|
|
141
|
+
- [OpenClaw](https://openclaw.ai)
|
|
142
|
+
- [MCP Specification](https://modelcontextprotocol.io)
|
|
143
|
+
|
|
144
|
+
## License
|
|
145
|
+
|
|
146
|
+
MIT
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* @aerostack/openclaw-bridge
|
|
4
|
+
*
|
|
5
|
+
* stdio-to-HTTP bridge connecting OpenClaw (and any stdio MCP client)
|
|
6
|
+
* to an Aerostack Workspace via Streamable HTTP transport.
|
|
7
|
+
*
|
|
8
|
+
* OpenClaw config:
|
|
9
|
+
* {
|
|
10
|
+
* "mcp": {
|
|
11
|
+
* "servers": {
|
|
12
|
+
* "my-workspace": {
|
|
13
|
+
* "command": "npx",
|
|
14
|
+
* "args": ["-y", "@aerostack/openclaw-bridge"],
|
|
15
|
+
* "env": {
|
|
16
|
+
* "AEROSTACK_WORKSPACE_URL": "https://api.aerostack.dev/api/gateway/ws/my-workspace",
|
|
17
|
+
* "AEROSTACK_TOKEN": "mwt_..."
|
|
18
|
+
* }
|
|
19
|
+
* }
|
|
20
|
+
* }
|
|
21
|
+
* }
|
|
22
|
+
* }
|
|
23
|
+
*/
|
|
24
|
+
export {};
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* @aerostack/openclaw-bridge
|
|
4
|
+
*
|
|
5
|
+
* stdio-to-HTTP bridge connecting OpenClaw (and any stdio MCP client)
|
|
6
|
+
* to an Aerostack Workspace via Streamable HTTP transport.
|
|
7
|
+
*
|
|
8
|
+
* OpenClaw config:
|
|
9
|
+
* {
|
|
10
|
+
* "mcp": {
|
|
11
|
+
* "servers": {
|
|
12
|
+
* "my-workspace": {
|
|
13
|
+
* "command": "npx",
|
|
14
|
+
* "args": ["-y", "@aerostack/openclaw-bridge"],
|
|
15
|
+
* "env": {
|
|
16
|
+
* "AEROSTACK_WORKSPACE_URL": "https://api.aerostack.dev/api/gateway/ws/my-workspace",
|
|
17
|
+
* "AEROSTACK_TOKEN": "mwt_..."
|
|
18
|
+
* }
|
|
19
|
+
* }
|
|
20
|
+
* }
|
|
21
|
+
* }
|
|
22
|
+
* }
|
|
23
|
+
*/
|
|
24
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
25
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
26
|
+
import { ListToolsRequestSchema, CallToolRequestSchema, ListResourcesRequestSchema, ReadResourceRequestSchema, ListPromptsRequestSchema, GetPromptRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
|
|
27
|
+
// ── Config ─────────────────────────────────────────────────────────
|
|
28
|
+
const WORKSPACE_URL = process.env.AEROSTACK_WORKSPACE_URL;
|
|
29
|
+
const TOKEN = process.env.AEROSTACK_TOKEN;
|
|
30
|
+
const APPROVAL_POLL_INTERVAL_MS = parseInt(process.env.AEROSTACK_APPROVAL_POLL_MS ?? '3000', 10);
|
|
31
|
+
const APPROVAL_TIMEOUT_MS = parseInt(process.env.AEROSTACK_APPROVAL_TIMEOUT_MS ?? '300000', 10); // 5 min
|
|
32
|
+
const REQUEST_TIMEOUT_MS = parseInt(process.env.AEROSTACK_REQUEST_TIMEOUT_MS ?? '30000', 10);
|
|
33
|
+
if (!WORKSPACE_URL) {
|
|
34
|
+
process.stderr.write('ERROR: AEROSTACK_WORKSPACE_URL is required\n');
|
|
35
|
+
process.exit(1);
|
|
36
|
+
}
|
|
37
|
+
if (!TOKEN) {
|
|
38
|
+
process.stderr.write('ERROR: AEROSTACK_TOKEN is required\n');
|
|
39
|
+
process.exit(1);
|
|
40
|
+
}
|
|
41
|
+
// Strip trailing slash
|
|
42
|
+
const baseUrl = WORKSPACE_URL.replace(/\/+$/, '');
|
|
43
|
+
async function rpcCall(method, params) {
|
|
44
|
+
const body = {
|
|
45
|
+
jsonrpc: '2.0',
|
|
46
|
+
id: Date.now(),
|
|
47
|
+
method,
|
|
48
|
+
params: params ?? {},
|
|
49
|
+
};
|
|
50
|
+
const controller = new AbortController();
|
|
51
|
+
const timer = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
|
|
52
|
+
try {
|
|
53
|
+
const res = await fetch(baseUrl, {
|
|
54
|
+
method: 'POST',
|
|
55
|
+
headers: {
|
|
56
|
+
'Content-Type': 'application/json',
|
|
57
|
+
'Authorization': `Bearer ${TOKEN}`,
|
|
58
|
+
'User-Agent': 'aerostack-openclaw-bridge/0.1.0',
|
|
59
|
+
'X-Agent-Id': 'openclaw',
|
|
60
|
+
},
|
|
61
|
+
body: JSON.stringify(body),
|
|
62
|
+
signal: controller.signal,
|
|
63
|
+
});
|
|
64
|
+
clearTimeout(timer);
|
|
65
|
+
const contentType = res.headers.get('content-type') ?? '';
|
|
66
|
+
// Handle SSE streaming — collect all data events and return the last JSON-RPC response
|
|
67
|
+
if (contentType.includes('text/event-stream')) {
|
|
68
|
+
const text = await res.text();
|
|
69
|
+
return parseSSEResponse(text, body.id);
|
|
70
|
+
}
|
|
71
|
+
const json = await res.json();
|
|
72
|
+
return json;
|
|
73
|
+
}
|
|
74
|
+
catch (err) {
|
|
75
|
+
clearTimeout(timer);
|
|
76
|
+
const message = err instanceof Error ? err.message : 'Unknown error';
|
|
77
|
+
if (err instanceof Error && err.name === 'AbortError') {
|
|
78
|
+
return { jsonrpc: '2.0', id: body.id, error: { code: -32603, message: 'Request timed out' } };
|
|
79
|
+
}
|
|
80
|
+
return { jsonrpc: '2.0', id: body.id, error: { code: -32603, message: `HTTP error: ${message}` } };
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
function parseSSEResponse(text, requestId) {
|
|
84
|
+
const lines = text.split('\n');
|
|
85
|
+
let lastData = null;
|
|
86
|
+
for (const line of lines) {
|
|
87
|
+
if (line.startsWith('data: ')) {
|
|
88
|
+
try {
|
|
89
|
+
lastData = JSON.parse(line.slice(6));
|
|
90
|
+
}
|
|
91
|
+
catch {
|
|
92
|
+
// skip malformed lines
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return lastData ?? { jsonrpc: '2.0', id: requestId, error: { code: -32603, message: 'Empty SSE response' } };
|
|
97
|
+
}
|
|
98
|
+
async function pollApproval(approvalId) {
|
|
99
|
+
const pollUrl = `${baseUrl}/approval-status/${approvalId}`;
|
|
100
|
+
const deadline = Date.now() + APPROVAL_TIMEOUT_MS;
|
|
101
|
+
process.stderr.write(`[aerostack-bridge] Tool requires approval (${approvalId}). Waiting...\n`);
|
|
102
|
+
while (Date.now() < deadline) {
|
|
103
|
+
await sleep(APPROVAL_POLL_INTERVAL_MS);
|
|
104
|
+
try {
|
|
105
|
+
const res = await fetch(pollUrl, {
|
|
106
|
+
headers: { 'User-Agent': 'aerostack-openclaw-bridge/0.1.0' },
|
|
107
|
+
});
|
|
108
|
+
if (!res.ok)
|
|
109
|
+
continue;
|
|
110
|
+
const status = await res.json();
|
|
111
|
+
if (status.status === 'executed') {
|
|
112
|
+
process.stderr.write(`[aerostack-bridge] Approved and executed.\n`);
|
|
113
|
+
return status;
|
|
114
|
+
}
|
|
115
|
+
if (status.status === 'approved') {
|
|
116
|
+
process.stderr.write(`[aerostack-bridge] Approved. Retrying tool call...\n`);
|
|
117
|
+
return status;
|
|
118
|
+
}
|
|
119
|
+
if (status.status === 'rejected') {
|
|
120
|
+
process.stderr.write(`[aerostack-bridge] Rejected: ${status.reviewer_note ?? 'no reason given'}\n`);
|
|
121
|
+
return status;
|
|
122
|
+
}
|
|
123
|
+
if (status.status === 'expired') {
|
|
124
|
+
process.stderr.write(`[aerostack-bridge] Approval expired.\n`);
|
|
125
|
+
return status;
|
|
126
|
+
}
|
|
127
|
+
// still pending — keep polling
|
|
128
|
+
}
|
|
129
|
+
catch {
|
|
130
|
+
// network error — keep trying
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
return { id: approvalId, status: 'expired', tool_name: '' };
|
|
134
|
+
}
|
|
135
|
+
function sleep(ms) {
|
|
136
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
137
|
+
}
|
|
138
|
+
// ── Handle tools/call with approval retry ──────────────────────────
|
|
139
|
+
async function callToolWithApproval(name, args) {
|
|
140
|
+
const response = await rpcCall('tools/call', { name, arguments: args });
|
|
141
|
+
// Check for approval-required error (-32050)
|
|
142
|
+
if (response.error?.code === -32050) {
|
|
143
|
+
const data = response.error.data;
|
|
144
|
+
const approvalId = data?.approval_id;
|
|
145
|
+
if (!approvalId) {
|
|
146
|
+
return { jsonrpc: '2.0', id: response.id, error: { code: -32603, message: 'Approval required but no approval_id returned' } };
|
|
147
|
+
}
|
|
148
|
+
const status = await pollApproval(approvalId);
|
|
149
|
+
if (status.status === 'rejected') {
|
|
150
|
+
return {
|
|
151
|
+
jsonrpc: '2.0',
|
|
152
|
+
id: response.id,
|
|
153
|
+
error: { code: -32603, message: `Tool call rejected: ${status.reviewer_note ?? 'no reason given'}` },
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
if (status.status === 'expired') {
|
|
157
|
+
return {
|
|
158
|
+
jsonrpc: '2.0',
|
|
159
|
+
id: response.id,
|
|
160
|
+
error: { code: -32603, message: 'Approval request expired' },
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
// Approved — retry the tool call (gateway will find the cached approval)
|
|
164
|
+
return rpcCall('tools/call', { name, arguments: args });
|
|
165
|
+
}
|
|
166
|
+
return response;
|
|
167
|
+
}
|
|
168
|
+
// ── MCP Server (stdio) ────────────────────────────────────────────
|
|
169
|
+
let cachedServerInfo = null;
|
|
170
|
+
async function ensureInitialized() {
|
|
171
|
+
if (cachedServerInfo)
|
|
172
|
+
return;
|
|
173
|
+
const res = await rpcCall('initialize', {
|
|
174
|
+
protocolVersion: '2024-11-05',
|
|
175
|
+
capabilities: {},
|
|
176
|
+
clientInfo: { name: 'aerostack-openclaw-bridge', version: '0.1.0' },
|
|
177
|
+
});
|
|
178
|
+
if (res.result) {
|
|
179
|
+
const r = res.result;
|
|
180
|
+
cachedServerInfo = {
|
|
181
|
+
protocolVersion: r.protocolVersion ?? '2024-11-05',
|
|
182
|
+
instructions: r.instructions,
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
const server = new Server({ name: 'aerostack-openclaw-bridge', version: '0.1.0' }, { capabilities: { tools: {}, resources: {}, prompts: {} } });
|
|
187
|
+
// ── tools/list ─────────────────────────────────────────────────────
|
|
188
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
189
|
+
await ensureInitialized();
|
|
190
|
+
const res = await rpcCall('tools/list');
|
|
191
|
+
if (res.error) {
|
|
192
|
+
throw new Error(res.error.message);
|
|
193
|
+
}
|
|
194
|
+
const result = res.result;
|
|
195
|
+
return { tools: result.tools ?? [] };
|
|
196
|
+
});
|
|
197
|
+
// ── tools/call ─────────────────────────────────────────────────────
|
|
198
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
199
|
+
await ensureInitialized();
|
|
200
|
+
const { name, arguments: args } = request.params;
|
|
201
|
+
const res = await callToolWithApproval(name, (args ?? {}));
|
|
202
|
+
if (res.error) {
|
|
203
|
+
return {
|
|
204
|
+
content: [{ type: 'text', text: `Error: ${res.error.message}` }],
|
|
205
|
+
isError: true,
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
const result = res.result;
|
|
209
|
+
return { content: result.content ?? [{ type: 'text', text: JSON.stringify(res.result) }] };
|
|
210
|
+
});
|
|
211
|
+
// ── resources/list ─────────────────────────────────────────────────
|
|
212
|
+
server.setRequestHandler(ListResourcesRequestSchema, async () => {
|
|
213
|
+
await ensureInitialized();
|
|
214
|
+
const res = await rpcCall('resources/list');
|
|
215
|
+
if (res.error) {
|
|
216
|
+
throw new Error(res.error.message);
|
|
217
|
+
}
|
|
218
|
+
const result = res.result;
|
|
219
|
+
return { resources: result.resources ?? [] };
|
|
220
|
+
});
|
|
221
|
+
// ── resources/read ─────────────────────────────────────────────────
|
|
222
|
+
server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
|
|
223
|
+
await ensureInitialized();
|
|
224
|
+
const res = await rpcCall('resources/read', { uri: request.params.uri });
|
|
225
|
+
if (res.error) {
|
|
226
|
+
throw new Error(res.error.message);
|
|
227
|
+
}
|
|
228
|
+
const result = res.result;
|
|
229
|
+
return { contents: result.contents ?? [] };
|
|
230
|
+
});
|
|
231
|
+
// ── prompts/list ───────────────────────────────────────────────────
|
|
232
|
+
server.setRequestHandler(ListPromptsRequestSchema, async () => {
|
|
233
|
+
await ensureInitialized();
|
|
234
|
+
const res = await rpcCall('prompts/list');
|
|
235
|
+
if (res.error) {
|
|
236
|
+
throw new Error(res.error.message);
|
|
237
|
+
}
|
|
238
|
+
const result = res.result;
|
|
239
|
+
return { prompts: result.prompts ?? [] };
|
|
240
|
+
});
|
|
241
|
+
// ── prompts/get ────────────────────────────────────────────────────
|
|
242
|
+
server.setRequestHandler(GetPromptRequestSchema, async (request) => {
|
|
243
|
+
await ensureInitialized();
|
|
244
|
+
const res = await rpcCall('prompts/get', {
|
|
245
|
+
name: request.params.name,
|
|
246
|
+
arguments: request.params.arguments,
|
|
247
|
+
});
|
|
248
|
+
if (res.error) {
|
|
249
|
+
throw new Error(res.error.message);
|
|
250
|
+
}
|
|
251
|
+
const result = res.result;
|
|
252
|
+
return { messages: result.messages ?? [] };
|
|
253
|
+
});
|
|
254
|
+
// ── Start ──────────────────────────────────────────────────────────
|
|
255
|
+
async function main() {
|
|
256
|
+
process.stderr.write(`[aerostack-bridge] Connecting to ${baseUrl}\n`);
|
|
257
|
+
const transport = new StdioServerTransport();
|
|
258
|
+
await server.connect(transport);
|
|
259
|
+
process.stderr.write(`[aerostack-bridge] Ready. Workspace: ${baseUrl}\n`);
|
|
260
|
+
}
|
|
261
|
+
main().catch((err) => {
|
|
262
|
+
process.stderr.write(`[aerostack-bridge] Fatal: ${err}\n`);
|
|
263
|
+
process.exit(1);
|
|
264
|
+
});
|
|
265
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@aerostack/openclaw-bridge",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "stdio-to-HTTP bridge connecting OpenClaw to Aerostack Workspaces via MCP",
|
|
5
|
+
"author": "Aerostack",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"main": "dist/index.js",
|
|
9
|
+
"types": "dist/index.d.ts",
|
|
10
|
+
"bin": {
|
|
11
|
+
"aerostack-openclaw-bridge": "dist/index.js"
|
|
12
|
+
},
|
|
13
|
+
"files": [
|
|
14
|
+
"dist"
|
|
15
|
+
],
|
|
16
|
+
"scripts": {
|
|
17
|
+
"build": "tsc",
|
|
18
|
+
"prepublishOnly": "npm run build"
|
|
19
|
+
},
|
|
20
|
+
"dependencies": {
|
|
21
|
+
"@modelcontextprotocol/sdk": "^1.25.3"
|
|
22
|
+
},
|
|
23
|
+
"devDependencies": {
|
|
24
|
+
"typescript": "~5.8.3",
|
|
25
|
+
"@types/node": "^22.0.0"
|
|
26
|
+
},
|
|
27
|
+
"engines": {
|
|
28
|
+
"node": ">=18"
|
|
29
|
+
},
|
|
30
|
+
"keywords": [
|
|
31
|
+
"aerostack",
|
|
32
|
+
"openclaw",
|
|
33
|
+
"mcp",
|
|
34
|
+
"model-context-protocol",
|
|
35
|
+
"bridge",
|
|
36
|
+
"stdio"
|
|
37
|
+
]
|
|
38
|
+
}
|