proteum 2.3.0 → 2.4.2
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/AGENTS.md +8 -3
- package/README.md +20 -15
- package/agents/project/AGENTS.md +16 -10
- package/agents/project/DOCUMENTATION.md +1326 -0
- package/agents/project/app-root/AGENTS.md +2 -2
- package/agents/project/diagnostics.md +10 -9
- package/agents/project/optimizations.md +1 -1
- package/agents/project/root/AGENTS.md +15 -8
- package/agents/project/server/services/AGENTS.md +1 -0
- package/agents/project/tests/AGENTS.md +1 -0
- package/cli/commands/db.ts +160 -0
- package/cli/commands/dev.ts +148 -25
- package/cli/commands/diagnose.ts +2 -0
- package/cli/commands/explain.ts +38 -9
- package/cli/commands/mcp.ts +126 -9
- package/cli/commands/orient.ts +44 -17
- package/cli/commands/runtime.ts +100 -17
- package/cli/mcp/router.ts +1028 -0
- package/cli/presentation/commands.ts +56 -25
- package/cli/presentation/help.ts +1 -1
- package/cli/runtime/commands.ts +163 -21
- package/cli/runtime/devSessions.ts +328 -2
- package/cli/runtime/mcpDaemon.ts +288 -0
- package/cli/runtime/ports.ts +151 -0
- package/cli/utils/agents.ts +94 -17
- package/cli/utils/appRoots.ts +232 -0
- package/common/dev/database.ts +226 -0
- package/common/dev/diagnostics.ts +1 -1
- package/common/dev/inspection.ts +8 -1
- package/common/dev/mcpPayloads.ts +456 -17
- package/common/dev/mcpServer.ts +51 -0
- package/docs/agent-routing.md +32 -21
- package/docs/dev-commands.md +1 -1
- package/docs/dev-sessions.md +3 -1
- package/docs/diagnostics.md +21 -20
- package/docs/mcp.md +114 -50
- package/docs/migrate-from-2.1.3.md +3 -5
- package/docs/request-tracing.md +3 -3
- package/package.json +10 -3
- package/server/app/devDiagnostics.ts +92 -0
- package/server/app/devMcp.ts +55 -0
- package/server/services/prisma/mariadb.ts +7 -3
- package/server/services/router/http/index.ts +25 -0
- package/server/services/router/request/ip.test.cjs +0 -1
- package/tests/agents-utils.test.cjs +58 -3
- package/tests/cli-mcp-command.test.cjs +327 -0
- package/tests/codex-mcp-usage.test.cjs +307 -0
- package/tests/dev-sessions.test.cjs +113 -0
- package/tests/dev-transpile-watch.test.cjs +0 -1
- package/tests/eslint-rules.test.cjs +0 -1
- package/tests/inspection.test.cjs +0 -1
- package/tests/mcp.test.cjs +769 -2
- package/tests/router-cache-config.test.cjs +0 -1
- package/vitest.config.mjs +9 -0
- package/cli/mcp/provider.ts +0 -365
- package/cli/mcp/stdio.ts +0 -16
package/cli/mcp/provider.ts
DELETED
|
@@ -1,365 +0,0 @@
|
|
|
1
|
-
import fs from 'fs-extra';
|
|
2
|
-
import got from 'got';
|
|
3
|
-
import path from 'path';
|
|
4
|
-
|
|
5
|
-
import { buildContractsDoctorResponse } from '../../common/dev/contractsDoctor';
|
|
6
|
-
import { buildDoctorResponse, type TDoctorResponse } from '../../common/dev/diagnostics';
|
|
7
|
-
import { buildOrientationResponse, explainOwner } from '../../common/dev/inspection';
|
|
8
|
-
import {
|
|
9
|
-
buildRuntimeStatusPayload,
|
|
10
|
-
compactDiagnoseResponse,
|
|
11
|
-
compactDoctorResponse,
|
|
12
|
-
compactExplainSummary,
|
|
13
|
-
compactLogsResponse,
|
|
14
|
-
compactOrientationResponse,
|
|
15
|
-
compactPerfRequestResponse,
|
|
16
|
-
compactPerfTopResponse,
|
|
17
|
-
compactTraceResponse,
|
|
18
|
-
resolveInstructionRouting,
|
|
19
|
-
} from '../../common/dev/mcpPayloads';
|
|
20
|
-
import type { TProteumMcpProvider } from '../../common/dev/mcpServer';
|
|
21
|
-
import type { TDevConsoleLogLevel, TDevConsoleLogsResponse } from '../../common/dev/console';
|
|
22
|
-
import type { TDiagnoseResponse } from '../../common/dev/inspection';
|
|
23
|
-
import type { TPerfRequestResponse, TPerfTopResponse } from '../../common/dev/performance';
|
|
24
|
-
import type { TProteumManifest } from '../../common/dev/proteumManifest';
|
|
25
|
-
import type { TRequestTraceResponse } from '../../common/dev/requestTrace';
|
|
26
|
-
import { readProteumManifest } from '../compiler/common/proteumManifest';
|
|
27
|
-
import { listDevSessionInspections, type TDevSessionInspection } from '../runtime/devSessions';
|
|
28
|
-
|
|
29
|
-
type TCliProteumMcpProviderArgs = {
|
|
30
|
-
appRoot: string;
|
|
31
|
-
sessionFilePath?: string;
|
|
32
|
-
url?: string;
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
type TRequestOptions = {
|
|
36
|
-
method?: 'GET' | 'POST';
|
|
37
|
-
searchParams?: Record<string, string>;
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
const normalizeBaseUrl = (value: string) => value.replace(/\/+$/, '');
|
|
41
|
-
const dedupe = <TValue>(values: TValue[]) => [...new Set(values)];
|
|
42
|
-
|
|
43
|
-
const buildBaseUrlCandidates = (value: string) => {
|
|
44
|
-
const normalized = normalizeBaseUrl(value);
|
|
45
|
-
|
|
46
|
-
try {
|
|
47
|
-
const parsed = new URL(normalized);
|
|
48
|
-
const port = parsed.port;
|
|
49
|
-
const pathname = parsed.pathname === '/' ? '' : parsed.pathname;
|
|
50
|
-
const search = parsed.search;
|
|
51
|
-
const hash = parsed.hash;
|
|
52
|
-
const buildUrl = (hostname: string) => `${parsed.protocol}//${hostname}${port ? `:${port}` : ''}${pathname}${search}${hash}`;
|
|
53
|
-
|
|
54
|
-
if (parsed.hostname === '127.0.0.1') return dedupe([normalized, buildUrl('localhost'), buildUrl('[::1]')]);
|
|
55
|
-
if (parsed.hostname === 'localhost') return dedupe([normalized, buildUrl('127.0.0.1'), buildUrl('[::1]')]);
|
|
56
|
-
if (parsed.hostname === '[::1]' || parsed.hostname === '::1') return dedupe([normalized, buildUrl('localhost'), buildUrl('127.0.0.1')]);
|
|
57
|
-
} catch (_error) {}
|
|
58
|
-
|
|
59
|
-
return [normalized];
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
const compactSession = (inspection: TDevSessionInspection) => ({
|
|
63
|
-
sessionFilePath: inspection.sessionFilePath,
|
|
64
|
-
live: inspection.live,
|
|
65
|
-
stale: inspection.stale,
|
|
66
|
-
invalid: inspection.invalid,
|
|
67
|
-
parseError: inspection.parseError,
|
|
68
|
-
pid: inspection.record?.pid,
|
|
69
|
-
routerPort: inspection.record?.routerPort,
|
|
70
|
-
publicUrl: inspection.record?.publicUrl,
|
|
71
|
-
state: inspection.record?.state,
|
|
72
|
-
startedAt: inspection.record?.startedAt,
|
|
73
|
-
updatedAt: inspection.record?.updatedAt,
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
const getSessionUrl = (inspection: TDevSessionInspection) => {
|
|
77
|
-
if (!inspection.record) return '';
|
|
78
|
-
if (inspection.record.publicUrl) return inspection.record.publicUrl.replace(/\/+$/, '');
|
|
79
|
-
return `http://localhost:${inspection.record.routerPort}`;
|
|
80
|
-
};
|
|
81
|
-
|
|
82
|
-
export class CliProteumMcpProvider implements TProteumMcpProvider {
|
|
83
|
-
private sessionsPromise?: Promise<TDevSessionInspection[]>;
|
|
84
|
-
|
|
85
|
-
public constructor(private args: TCliProteumMcpProviderArgs) {}
|
|
86
|
-
|
|
87
|
-
private readManifestIfAvailable() {
|
|
88
|
-
const manifestFilepath = path.join(this.args.appRoot, '.proteum', 'manifest.json');
|
|
89
|
-
if (!fs.existsSync(manifestFilepath)) return undefined;
|
|
90
|
-
|
|
91
|
-
try {
|
|
92
|
-
return readProteumManifest(this.args.appRoot);
|
|
93
|
-
} catch (_error) {
|
|
94
|
-
return undefined;
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
private readLocalManifest() {
|
|
99
|
-
const manifest = this.readManifestIfAvailable();
|
|
100
|
-
if (!manifest) {
|
|
101
|
-
throw new Error(
|
|
102
|
-
`Proteum manifest was not found in ${this.args.appRoot}. Run \`proteum refresh\`, \`proteum dev\`, or pass --url for a running dev server.`,
|
|
103
|
-
);
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
return manifest;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
private async readSessions() {
|
|
110
|
-
this.sessionsPromise ??= listDevSessionInspections({
|
|
111
|
-
appRoot: this.args.appRoot,
|
|
112
|
-
sessionFilePath: this.args.sessionFilePath,
|
|
113
|
-
});
|
|
114
|
-
return await this.sessionsPromise;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
private async selectSession() {
|
|
118
|
-
const sessions = await this.readSessions();
|
|
119
|
-
const liveSessions = sessions.filter((inspection) => inspection.live && inspection.record);
|
|
120
|
-
|
|
121
|
-
return (
|
|
122
|
-
liveSessions.find((inspection) => inspection.record?.state === 'ready') ||
|
|
123
|
-
liveSessions[0] ||
|
|
124
|
-
sessions.find((inspection) => inspection.record)
|
|
125
|
-
);
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
private async getBaseUrlCandidates() {
|
|
129
|
-
if (this.args.url?.trim()) return buildBaseUrlCandidates(this.args.url.trim());
|
|
130
|
-
|
|
131
|
-
const selectedSession = await this.selectSession();
|
|
132
|
-
const selectedBaseUrl = selectedSession ? getSessionUrl(selectedSession) : '';
|
|
133
|
-
if (selectedBaseUrl) return buildBaseUrlCandidates(selectedBaseUrl);
|
|
134
|
-
|
|
135
|
-
const manifest = this.readManifestIfAvailable();
|
|
136
|
-
const routerPort = manifest?.env.resolved.routerPort;
|
|
137
|
-
if (typeof routerPort === 'number' && routerPort > 0) {
|
|
138
|
-
return dedupe([`http://localhost:${routerPort}`, `http://127.0.0.1:${routerPort}`, `http://[::1]:${routerPort}`]);
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
return [];
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
private async requestJson<TResponse>(pathname: string, options: TRequestOptions = {}) {
|
|
145
|
-
const attempts: string[] = [];
|
|
146
|
-
const baseUrls = await this.getBaseUrlCandidates();
|
|
147
|
-
|
|
148
|
-
for (const baseUrl of baseUrls) {
|
|
149
|
-
const url = `${baseUrl}${pathname}${options.searchParams ? `?${new URLSearchParams(options.searchParams).toString()}` : ''}`;
|
|
150
|
-
|
|
151
|
-
try {
|
|
152
|
-
const response = await got(url, {
|
|
153
|
-
method: options.method || 'GET',
|
|
154
|
-
responseType: 'json',
|
|
155
|
-
retry: { limit: 0 },
|
|
156
|
-
throwHttpErrors: false,
|
|
157
|
-
timeout: { request: 2_500 },
|
|
158
|
-
});
|
|
159
|
-
|
|
160
|
-
if (response.statusCode >= 400) {
|
|
161
|
-
const body = response.body as { error?: string } | undefined;
|
|
162
|
-
throw new Error(body?.error || `Proteum dev endpoint returned HTTP ${response.statusCode}.`);
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
return { baseUrl, body: response.body as TResponse };
|
|
166
|
-
} catch (error) {
|
|
167
|
-
attempts.push(`${url}: ${error instanceof Error ? error.message : String(error)}`);
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
throw new Error(
|
|
172
|
-
[
|
|
173
|
-
'Could not reach a Proteum dev MCP data source.',
|
|
174
|
-
...attempts.map((attempt) => `- ${attempt}`),
|
|
175
|
-
'Start `proteum dev`, pass --url, or use tools that can read the local manifest from disk.',
|
|
176
|
-
].join('\n'),
|
|
177
|
-
);
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
private async readManifestPreferRuntime() {
|
|
181
|
-
if (this.args.url?.trim()) {
|
|
182
|
-
return (await this.requestJson<TProteumManifest>('/__proteum/explain')).body;
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
const localManifest = this.readManifestIfAvailable();
|
|
186
|
-
if (localManifest) return localManifest;
|
|
187
|
-
|
|
188
|
-
return (await this.requestJson<TProteumManifest>('/__proteum/explain')).body;
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
private async probeRuntimeHealth() {
|
|
192
|
-
try {
|
|
193
|
-
const response = await this.requestJson<TDoctorResponse>('/__proteum/doctor');
|
|
194
|
-
return {
|
|
195
|
-
reachable: true,
|
|
196
|
-
baseUrl: response.baseUrl,
|
|
197
|
-
doctor: response.body.summary,
|
|
198
|
-
};
|
|
199
|
-
} catch (error) {
|
|
200
|
-
return {
|
|
201
|
-
reachable: false,
|
|
202
|
-
error: error instanceof Error ? error.message : String(error),
|
|
203
|
-
};
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
public async runtimeStatus(_input: Record<string, never> = {}) {
|
|
208
|
-
const manifest = this.readManifestIfAvailable();
|
|
209
|
-
const sessions = await this.readSessions();
|
|
210
|
-
const selectedSession = await this.selectSession();
|
|
211
|
-
const health = await this.probeRuntimeHealth();
|
|
212
|
-
const runtime =
|
|
213
|
-
health.reachable && 'baseUrl' in health
|
|
214
|
-
? {
|
|
215
|
-
publicUrl: health.baseUrl,
|
|
216
|
-
routerPort: selectedSession?.record?.routerPort || manifest?.env.resolved.routerPort,
|
|
217
|
-
source: this.args.url?.trim() ? 'explicit-url' : selectedSession?.record ? 'tracked-session' : 'manifest-port',
|
|
218
|
-
session: selectedSession ? compactSession(selectedSession) : undefined,
|
|
219
|
-
mcpUrl: `${health.baseUrl}/__proteum/mcp`,
|
|
220
|
-
}
|
|
221
|
-
: selectedSession
|
|
222
|
-
? {
|
|
223
|
-
routerPort: selectedSession.record?.routerPort,
|
|
224
|
-
publicUrl: selectedSession.record?.publicUrl,
|
|
225
|
-
source: 'tracked-session',
|
|
226
|
-
session: compactSession(selectedSession),
|
|
227
|
-
}
|
|
228
|
-
: undefined;
|
|
229
|
-
|
|
230
|
-
return buildRuntimeStatusPayload({
|
|
231
|
-
appRoot: this.args.appRoot,
|
|
232
|
-
health,
|
|
233
|
-
manifest,
|
|
234
|
-
runtime,
|
|
235
|
-
sessions: sessions.map(compactSession),
|
|
236
|
-
});
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
public async orient({ query }: { query: string }) {
|
|
240
|
-
return compactOrientationResponse(buildOrientationResponse(await this.readManifestPreferRuntime(), query));
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
public async instructionsResolve({ query }: { query?: string }) {
|
|
244
|
-
return resolveInstructionRouting({ appRoot: this.args.appRoot, query });
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
public async explainSummary({ query }: { query?: string }) {
|
|
248
|
-
const manifest = await this.readManifestPreferRuntime();
|
|
249
|
-
const normalizedQuery = query?.trim();
|
|
250
|
-
|
|
251
|
-
return compactExplainSummary({
|
|
252
|
-
manifest,
|
|
253
|
-
owner: normalizedQuery ? explainOwner(manifest, normalizedQuery) : undefined,
|
|
254
|
-
query: normalizedQuery,
|
|
255
|
-
});
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
public async doctor({ contracts = true }: { contracts?: boolean }) {
|
|
259
|
-
if (this.args.url?.trim()) {
|
|
260
|
-
const doctor = (await this.requestJson<TDoctorResponse>('/__proteum/doctor')).body;
|
|
261
|
-
const contractDoctor = contracts
|
|
262
|
-
? (await this.requestJson<TDoctorResponse>('/__proteum/doctor/contracts')).body
|
|
263
|
-
: undefined;
|
|
264
|
-
return compactDoctorResponse({ contracts: contractDoctor, doctor });
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
const manifest = this.readManifestIfAvailable();
|
|
268
|
-
if (manifest) {
|
|
269
|
-
return compactDoctorResponse({
|
|
270
|
-
contracts: contracts ? buildContractsDoctorResponse(manifest) : undefined,
|
|
271
|
-
doctor: buildDoctorResponse(manifest),
|
|
272
|
-
});
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
const doctor = (await this.requestJson<TDoctorResponse>('/__proteum/doctor')).body;
|
|
276
|
-
const contractDoctor = contracts
|
|
277
|
-
? (await this.requestJson<TDoctorResponse>('/__proteum/doctor/contracts')).body
|
|
278
|
-
: undefined;
|
|
279
|
-
return compactDoctorResponse({ contracts: contractDoctor, doctor });
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
public async diagnose(input: {
|
|
283
|
-
logsLevel?: TDevConsoleLogLevel;
|
|
284
|
-
logsLimit?: number;
|
|
285
|
-
path?: string;
|
|
286
|
-
query?: string;
|
|
287
|
-
requestId?: string;
|
|
288
|
-
}) {
|
|
289
|
-
const searchParams: Record<string, string> = {};
|
|
290
|
-
if (input.logsLevel) searchParams.logsLevel = input.logsLevel;
|
|
291
|
-
if (typeof input.logsLimit === 'number') searchParams.logsLimit = String(input.logsLimit);
|
|
292
|
-
if (input.path) searchParams.path = input.path;
|
|
293
|
-
if (input.query) searchParams.query = input.query;
|
|
294
|
-
if (input.requestId) searchParams.requestId = input.requestId;
|
|
295
|
-
|
|
296
|
-
return compactDiagnoseResponse((await this.requestJson<TDiagnoseResponse>('/__proteum/diagnose', { searchParams })).body);
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
public async traceLatest(input: { detail?: 'compact' | 'full'; limit?: number; offset?: number }) {
|
|
300
|
-
const response = (await this.requestJson<TRequestTraceResponse>('/__proteum/trace/latest')).body;
|
|
301
|
-
return compactTraceResponse({
|
|
302
|
-
detail: input.detail,
|
|
303
|
-
limit: input.limit,
|
|
304
|
-
offset: input.offset,
|
|
305
|
-
request: response.request,
|
|
306
|
-
});
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
public async traceShow(input: { detail?: 'compact' | 'full'; limit?: number; offset?: number; requestId: string }) {
|
|
310
|
-
const response = (await this.requestJson<TRequestTraceResponse>(`/__proteum/trace/requests/${encodeURIComponent(input.requestId)}`))
|
|
311
|
-
.body;
|
|
312
|
-
return compactTraceResponse({
|
|
313
|
-
detail: input.detail,
|
|
314
|
-
limit: input.limit,
|
|
315
|
-
offset: input.offset,
|
|
316
|
-
request: response.request,
|
|
317
|
-
});
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
public async perfTop(input: { groupBy?: 'path' | 'route' | 'controller'; limit?: number; since?: string }) {
|
|
321
|
-
return compactPerfTopResponse(
|
|
322
|
-
(
|
|
323
|
-
await this.requestJson<TPerfTopResponse>('/__proteum/perf/top', {
|
|
324
|
-
searchParams: {
|
|
325
|
-
groupBy: input.groupBy || 'path',
|
|
326
|
-
limit: String(input.limit || 12),
|
|
327
|
-
since: input.since || 'today',
|
|
328
|
-
},
|
|
329
|
-
})
|
|
330
|
-
).body,
|
|
331
|
-
);
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
public async perfRequest({ query }: { query: string }) {
|
|
335
|
-
return compactPerfRequestResponse(
|
|
336
|
-
(
|
|
337
|
-
await this.requestJson<TPerfRequestResponse>('/__proteum/perf/request', {
|
|
338
|
-
searchParams: { query },
|
|
339
|
-
})
|
|
340
|
-
).body,
|
|
341
|
-
);
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
public async logsTail({ level = 'warn', limit = 40 }: { level?: TDevConsoleLogLevel; limit?: number }) {
|
|
345
|
-
return compactLogsResponse({
|
|
346
|
-
level,
|
|
347
|
-
limit,
|
|
348
|
-
response: (
|
|
349
|
-
await this.requestJson<TDevConsoleLogsResponse>('/__proteum/logs', {
|
|
350
|
-
searchParams: { level, limit: String(limit) },
|
|
351
|
-
})
|
|
352
|
-
).body,
|
|
353
|
-
});
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
public async readResource(uri: string) {
|
|
357
|
-
if (uri === 'proteum://runtime/status') return await this.runtimeStatus({});
|
|
358
|
-
if (uri === 'proteum://instructions/router') return await this.instructionsResolve({});
|
|
359
|
-
if (uri === 'proteum://manifest/summary') return await this.explainSummary({});
|
|
360
|
-
if (uri === 'proteum://trace/latest/summary') return await this.traceLatest({});
|
|
361
|
-
if (uri === 'proteum://perf/top') return await this.perfTop({});
|
|
362
|
-
|
|
363
|
-
throw new Error(`Unknown Proteum MCP resource: ${uri}`);
|
|
364
|
-
}
|
|
365
|
-
}
|
package/cli/mcp/stdio.ts
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
2
|
-
|
|
3
|
-
import { createProteumMcpServer, type TProteumMcpProvider } from '../../common/dev/mcpServer';
|
|
4
|
-
|
|
5
|
-
export const startProteumMcpStdioServer = async ({
|
|
6
|
-
provider,
|
|
7
|
-
version,
|
|
8
|
-
}: {
|
|
9
|
-
provider: TProteumMcpProvider;
|
|
10
|
-
version: string;
|
|
11
|
-
}) => {
|
|
12
|
-
const server = createProteumMcpServer({ provider, version });
|
|
13
|
-
const transport = new StdioServerTransport();
|
|
14
|
-
|
|
15
|
-
await server.connect(transport);
|
|
16
|
-
};
|