progmune-runtime 2.0.2 → 2.0.4

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,186 @@
1
+ [
2
+ {
3
+ "intent": "生成一个JWT令牌",
4
+ "actions": [
5
+ {
6
+ "kind": "assign",
7
+ "target": "payload",
8
+ "value": "user:123"
9
+ },
10
+ {
11
+ "kind": "call",
12
+ "function": "generate_jwt",
13
+ "args": [
14
+ {
15
+ "name": "payload",
16
+ "type": "UserPayload",
17
+ "value": "payload"
18
+ }
19
+ ],
20
+ "assignTo": "token"
21
+ },
22
+ {
23
+ "kind": "return",
24
+ "value": "token"
25
+ }
26
+ ],
27
+ "success": true,
28
+ "id": "ep_1778775611414",
29
+ "timestamp": "2026-05-14T16:20:11.414Z"
30
+ },
31
+ {
32
+ "intent": "生成一个JWT令牌",
33
+ "actions": [],
34
+ "success": false,
35
+ "id": "ep_1778775591074",
36
+ "timestamp": "2026-05-14T16:19:51.074Z"
37
+ },
38
+ {
39
+ "intent": "生成一个JWT令牌",
40
+ "actions": [
41
+ {
42
+ "kind": "assign",
43
+ "target": "payload",
44
+ "value": "user:123"
45
+ },
46
+ {
47
+ "kind": "call",
48
+ "function": "generate_jwt",
49
+ "args": [
50
+ {
51
+ "name": "payload",
52
+ "type": "UserPayload",
53
+ "value": "payload"
54
+ }
55
+ ],
56
+ "assignTo": "token"
57
+ },
58
+ {
59
+ "kind": "return",
60
+ "value": "token"
61
+ }
62
+ ],
63
+ "success": true,
64
+ "id": "ep_1778775315729",
65
+ "timestamp": "2026-05-14T16:15:15.729Z"
66
+ },
67
+ {
68
+ "intent": "生成一个JWT令牌",
69
+ "actions": [
70
+ {
71
+ "kind": "assign",
72
+ "target": "payload",
73
+ "value": "user:123"
74
+ },
75
+ {
76
+ "kind": "call",
77
+ "function": "generate_jwt",
78
+ "args": [
79
+ {
80
+ "name": "payload",
81
+ "type": "UserPayload",
82
+ "value": "payload"
83
+ }
84
+ ],
85
+ "assignTo": "token"
86
+ },
87
+ {
88
+ "kind": "return",
89
+ "value": "token"
90
+ }
91
+ ],
92
+ "success": true,
93
+ "id": "ep_1778775173516",
94
+ "timestamp": "2026-05-14T16:12:53.516Z"
95
+ },
96
+ {
97
+ "intent": "创建一个带令牌的会话",
98
+ "actions": [
99
+ {
100
+ "kind": "assign",
101
+ "target": "user_payload",
102
+ "value": "user:123"
103
+ },
104
+ {
105
+ "kind": "call",
106
+ "function": "query_data",
107
+ "args": [
108
+ {
109
+ "name": "key",
110
+ "type": "str",
111
+ "value": "user_payload"
112
+ }
113
+ ],
114
+ "assignTo": "user_data"
115
+ },
116
+ {
117
+ "kind": "assign",
118
+ "target": "plain_password",
119
+ "value": "password123"
120
+ },
121
+ {
122
+ "kind": "call",
123
+ "function": "verify_password",
124
+ "args": [
125
+ {
126
+ "name": "plain",
127
+ "type": "str",
128
+ "value": "plain_password"
129
+ },
130
+ {
131
+ "name": "hash",
132
+ "type": "PasswordHash",
133
+ "value": "user_data"
134
+ }
135
+ ],
136
+ "assignTo": "password_valid"
137
+ },
138
+ {
139
+ "kind": "call",
140
+ "function": "generate_jwt",
141
+ "args": [
142
+ {
143
+ "name": "payload",
144
+ "type": "UserPayload",
145
+ "value": "user_payload"
146
+ }
147
+ ],
148
+ "assignTo": "token"
149
+ },
150
+ {
151
+ "kind": "call",
152
+ "function": "create_session",
153
+ "args": [
154
+ {
155
+ "name": "user",
156
+ "type": "UserPayload",
157
+ "value": "user_payload"
158
+ },
159
+ {
160
+ "name": "token",
161
+ "type": "Token",
162
+ "value": "token"
163
+ }
164
+ ],
165
+ "assignTo": "session"
166
+ },
167
+ {
168
+ "kind": "return",
169
+ "value": "session"
170
+ },
171
+ {
172
+ "kind": "return",
173
+ "value": "error"
174
+ },
175
+ {
176
+ "kind": "if",
177
+ "condition": "password_valid",
178
+ "thenActions": [],
179
+ "elseActions": []
180
+ }
181
+ ],
182
+ "success": true,
183
+ "id": "ep_1778775082912",
184
+ "timestamp": "2026-05-14T16:11:22.919Z"
185
+ }
186
+ ]
@@ -0,0 +1,126 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.extractFingerprints = extractFingerprints;
37
+ exports.reportFingerprints = reportFingerprints;
38
+ exports.previewFingerprints = previewFingerprints;
39
+ const fs = __importStar(require("fs"));
40
+ const path = __importStar(require("path"));
41
+ const https = __importStar(require("https"));
42
+ const http = __importStar(require("http"));
43
+ const crypto = __importStar(require("crypto"));
44
+ const REPORT_ENDPOINT = process.env.PROGMUNE_HUB || "http://localhost:3000/report";
45
+ const FINGERPRINT_FILE = path.resolve(__dirname, "../.progmune_memory/fingerprints.json");
46
+ function getInstanceId() {
47
+ const host = require("os").hostname();
48
+ const cwd = process.cwd();
49
+ return crypto.createHash("sha256").update(host + cwd).digest("hex").substring(0, 16);
50
+ }
51
+ function extractFingerprints() {
52
+ const corpusDir = path.resolve(__dirname, "../failure_corpus");
53
+ if (!fs.existsSync(corpusDir))
54
+ return [];
55
+ const fingerprints = [];
56
+ const instanceId = getInstanceId();
57
+ for (const dateDir of fs.readdirSync(corpusDir)) {
58
+ const datePath = path.join(corpusDir, dateDir);
59
+ if (!fs.statSync(datePath).isDirectory())
60
+ continue;
61
+ for (const file of fs.readdirSync(datePath)) {
62
+ if (!file.endsWith(".json"))
63
+ continue;
64
+ const record = JSON.parse(fs.readFileSync(path.join(datePath, file), "utf-8"));
65
+ const funcSeq = (record.actionSequence || [])
66
+ .filter((a) => a.kind === "call")
67
+ .map((a) => a.function);
68
+ fingerprints.push({
69
+ instance_id: instanceId,
70
+ timestamp: record.timestamp,
71
+ violatedSVL: record.violatedSVL,
72
+ constraintType: record.constraintType,
73
+ functionSequence: funcSeq,
74
+ preState: record.ssgState ? [record.ssgState] : undefined,
75
+ postState: undefined,
76
+ count: 1,
77
+ });
78
+ }
79
+ }
80
+ return fingerprints;
81
+ }
82
+ async function reportFingerprints() {
83
+ const fingerprints = extractFingerprints();
84
+ if (fingerprints.length === 0) {
85
+ return { success: true, message: "无新指纹需要上报" };
86
+ }
87
+ let reported = [];
88
+ if (fs.existsSync(FINGERPRINT_FILE)) {
89
+ reported = JSON.parse(fs.readFileSync(FINGERPRINT_FILE, "utf-8"));
90
+ }
91
+ const newFingerprints = fingerprints.filter(f => !reported.includes(f.functionSequence.join(",")));
92
+ if (newFingerprints.length === 0) {
93
+ return { success: true, message: "所有指纹已上报,无新增" };
94
+ }
95
+ const payload = JSON.stringify({ fingerprints: newFingerprints });
96
+ return new Promise((resolve) => {
97
+ const url = new URL(REPORT_ENDPOINT);
98
+ const transport = url.protocol === "https:" ? https : http;
99
+ const req = transport.request(REPORT_ENDPOINT, {
100
+ method: "POST",
101
+ headers: { "Content-Type": "application/json" },
102
+ }, (res) => {
103
+ let data = "";
104
+ res.on("data", (chunk) => data += chunk);
105
+ res.on("end", () => {
106
+ if (res.statusCode === 200) {
107
+ const updated = [...reported, ...newFingerprints.map(f => f.functionSequence.join(","))];
108
+ const dir = path.dirname(FINGERPRINT_FILE);
109
+ if (!fs.existsSync(dir))
110
+ fs.mkdirSync(dir, { recursive: true });
111
+ fs.writeFileSync(FINGERPRINT_FILE, JSON.stringify(updated, null, 2));
112
+ resolve({ success: true, message: `成功上报 ${newFingerprints.length} 条新指纹` });
113
+ }
114
+ else {
115
+ resolve({ success: false, message: `上报失败: ${res.statusCode} ${data}` });
116
+ }
117
+ });
118
+ });
119
+ req.on("error", (e) => resolve({ success: false, message: `网络错误: ${e.message}` }));
120
+ req.write(payload);
121
+ req.end();
122
+ });
123
+ }
124
+ function previewFingerprints() {
125
+ return extractFingerprints();
126
+ }
@@ -10,15 +10,13 @@ import * as path from 'path';
10
10
  const require = createRequire(import.meta.url);
11
11
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
12
12
 
13
- // ========== 处理 opt-in 子命令 ==========
13
+ // 处理命令行子命令
14
14
  const args = process.argv.slice(2);
15
15
  const OPT_IN_FILE = path.resolve(__dirname, '../.progmune_memory/opt_in.json');
16
-
17
16
  if (args[0] === 'opt-in') {
18
17
  const command = args[1] || 'status';
19
18
  const dir = path.dirname(OPT_IN_FILE);
20
19
  if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
21
-
22
20
  if (command === 'enable') {
23
21
  fs.writeFileSync(OPT_IN_FILE, JSON.stringify({ enabled: true, timestamp: new Date().toISOString() }, null, 2));
24
22
  console.log('✅ 已开启免疫网络上报。感谢您为全球免疫网络做出贡献!');
@@ -28,7 +26,6 @@ if (args[0] === 'opt-in') {
28
26
  if (fs.existsSync(OPT_IN_FILE)) fs.unlinkSync(OPT_IN_FILE);
29
27
  console.log('⛔ 已关闭免疫网络上报。Progmune 将以完全离线模式运行。');
30
28
  } else {
31
- // 显示当前状态
32
29
  if (fs.existsSync(OPT_IN_FILE)) {
33
30
  console.log('免疫网络上报状态: 已开启');
34
31
  console.log('脱敏错误指纹将自动上报。');
@@ -43,12 +40,25 @@ if (args[0] === 'opt-in') {
43
40
  process.exit(0);
44
41
  }
45
42
 
46
- // ========== MCP 服务器部分 ==========
47
43
  const { plan } = require('./planner.js');
48
44
  const { extractIRPython } = require('./extract-ir-python.js');
49
45
  const { emitPython } = require('./python-emitter.js');
50
46
  const { recordRun } = require('./feedback.js');
51
47
 
48
+ // 从独立的协议文件中加载协议,并注入到 IR 中
49
+ function mergeProtocols(irArray) {
50
+ const protocolsFile = path.resolve(__dirname, '../protocols.json');
51
+ if (!fs.existsSync(protocolsFile)) return irArray;
52
+
53
+ const protocols = JSON.parse(fs.readFileSync(protocolsFile, 'utf-8'));
54
+ return irArray.map(fn => {
55
+ if (protocols[fn.name]) {
56
+ return { ...fn, protocol: protocols[fn.name] };
57
+ }
58
+ return fn;
59
+ });
60
+ }
61
+
52
62
  async function main() {
53
63
  const server = new Server({
54
64
  name: "progmune",
@@ -74,19 +84,19 @@ async function main() {
74
84
  if (request.params.name === "progmune_generate") {
75
85
  const { intent, projectPath } = request.params.arguments;
76
86
 
77
- // 前置检查 LLM_API_KEY
78
87
  if (!process.env.LLM_API_KEY) {
79
88
  return { content: [{ type: "text", text: "❌ 未设置 LLM_API_KEY。请在终端执行:\nexport LLM_API_KEY='你的密钥'\n然后重启客户端。" }] };
80
89
  }
81
90
 
82
- // 前置检查免疫网络配置
83
91
  if (!fs.existsSync(OPT_IN_FILE)) {
84
92
  return { content: [{ type: "text", text: "⚠️ 请先完成免疫网络配置。\n\n运行以下命令开启(推荐):\n npx progmune-runtime opt-in enable\n\n或运行以下命令以离线模式使用:\n npx progmune-runtime opt-in disable\n\n配置完成后重启客户端即可使用。" }] };
85
93
  }
86
94
 
87
- // 执行规划
88
95
  const fns = extractIRPython(projectPath);
89
- fs.writeFileSync("ir.json", JSON.stringify(fns, null, 2));
96
+ // 关键步骤:将协议信息合并到 IR
97
+ const irWithProtocols = mergeProtocols(fns);
98
+ fs.writeFileSync("ir.json", JSON.stringify(irWithProtocols, null, 2));
99
+
90
100
  const actions = await plan(intent);
91
101
  if (!actions || actions.length === 0) {
92
102
  return { content: [{ type: "text", text: "无法生成满足约束的代码。" }] };
package/dist/planner.js CHANGED
@@ -42,6 +42,7 @@ const feedback_1 = require("./feedback");
42
42
  const utils_1 = require("./utils");
43
43
  const failure_corpus_1 = require("./failure-corpus");
44
44
  const memory_layer_1 = require("./memory-layer");
45
+ const ssg_validator_1 = require("./ssg-validator");
45
46
  const fs = __importStar(require("fs"));
46
47
  function enrichActions(actions, ir) {
47
48
  return actions.map(a => {
@@ -87,17 +88,36 @@ function determineConstraintType(svl) {
87
88
  case "SVL-4": return "protocol";
88
89
  }
89
90
  }
91
+ /** 加载 IR 中所有带 protocol 的函数为协议规则 */
92
+ function loadProtocols(ir) {
93
+ return ir
94
+ .filter((f) => f.protocol)
95
+ .map((f) => ({ function: f.name, protocol: f.protocol }));
96
+ }
97
+ /** 验证动作序列的协议合法性 */
98
+ function validateProtocol(actions, protocols, initialState) {
99
+ const ssv = new ssg_validator_1.StateMachineValidator(protocols, initialState);
100
+ for (let i = 0; i < actions.length; i++) {
101
+ const a = actions[i];
102
+ if (a.kind === "call" && a.function) {
103
+ const result = ssv.apply(a.function);
104
+ if (!result.valid) {
105
+ return { valid: false, error: result.error, index: i };
106
+ }
107
+ }
108
+ }
109
+ return { valid: true };
110
+ }
90
111
  async function plan(userIntent) {
91
112
  (0, llm_1.resetCallCount)();
92
113
  const ir = JSON.parse(fs.readFileSync("ir.json", "utf-8"));
93
- // ========== 语义模板快速通道 ==========
114
+ // 语义模板快速通道
94
115
  const cachedTemplate = (0, memory_layer_1.findSemanticTemplate)(userIntent);
95
116
  if (cachedTemplate && cachedTemplate.successRate >= 0.8 && cachedTemplate.useCount >= 2) {
96
117
  console.log("⚡ 命中语义模板,直接复用已验证序列");
97
118
  (0, memory_layer_1.recordEpisode)({ intent: userIntent, actions: cachedTemplate.actionSequence, success: true });
98
119
  return cachedTemplate.actionSequence;
99
120
  }
100
- // ====================================
101
121
  const keywords = (0, utils_1.extractKeywords)(userIntent);
102
122
  const scored = ir.map((f) => {
103
123
  let score = 0;
@@ -159,6 +179,8 @@ ${userIntent}
159
179
  只输出代码。`;
160
180
  let finalActions = [];
161
181
  let currentPrompt = basePrompt;
182
+ // 加载协议规则,设定初始状态(例如未认证场景)
183
+ const protocols = loadProtocols(ir);
162
184
  for (let r = 0; r < 3; r++) {
163
185
  let text;
164
186
  try {
@@ -179,6 +201,7 @@ ${userIntent}
179
201
  }
180
202
  const enriched = enrichActions(rawActions, ir);
181
203
  const filtered = enriched.filter(a => !forbiddenFuncs.includes(a.function || ''));
204
+ // 1) 基础序列校验
182
205
  const seqResult = (0, validator_1.validateActionSequence)(filtered);
183
206
  if (!seqResult.valid) {
184
207
  const errorsFlat = seqResult.errors.flat();
@@ -196,6 +219,26 @@ ${userIntent}
196
219
  currentPrompt = basePrompt + `\n错误:${errorsFlat.join(";")}。请修正。`;
197
220
  continue;
198
221
  }
222
+ // 2) 协议状态机校验 (SSG)
223
+ if (protocols.length > 0) {
224
+ const protoResult = validateProtocol(filtered, protocols, "UNAUTHENTICATED");
225
+ if (!protoResult.valid) {
226
+ console.log("🛡️ SSG 协议违规:", protoResult.error);
227
+ (0, failure_corpus_1.recordFailure)({
228
+ intent: userIntent,
229
+ projectFunctions: ir.map((f) => f.name),
230
+ violatedSVL: "SVL-4",
231
+ constraintType: "protocol",
232
+ actionSequence: filtered,
233
+ errorDetail: protoResult.error,
234
+ });
235
+ (0, memory_layer_1.recordEpisode)({ intent: userIntent, actions: filtered, success: false, svlViolated: "SVL-4" });
236
+ currentPrompt = basePrompt + `\n协议错误:${protoResult.error}。请按照正确的业务顺序重新生成,确保先通过认证再签发令牌。`;
237
+ continue;
238
+ continue;
239
+ }
240
+ }
241
+ // 3) 语义合约校验
199
242
  const semResult = (0, semantic_validator_1.checkSemantic)(userIntent, filtered);
200
243
  if (!semResult.valid) {
201
244
  console.log("⚠️ 语义校验失败:", semResult.errors.join(", "));
package/dist/report.js ADDED
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const immune_reporter_1 = require("./immune-reporter");
4
+ const args = process.argv.slice(2);
5
+ const command = args[0] || "preview";
6
+ async function main() {
7
+ switch (command) {
8
+ case "preview":
9
+ console.log("═══ 待上报的脱敏错误指纹 ═══");
10
+ const fps = (0, immune_reporter_1.previewFingerprints)();
11
+ if (fps.length === 0) {
12
+ console.log("(暂无新的失败案例)");
13
+ }
14
+ else {
15
+ fps.forEach((f, i) => {
16
+ console.log(`${i + 1}. [${f.violatedSVL}:${f.constraintType}] ${f.functionSequence.join(" → ") || "(无函数调用)"}`);
17
+ });
18
+ console.log(`\n共 ${fps.length} 条脱敏指纹待上报`);
19
+ }
20
+ break;
21
+ case "report":
22
+ console.log("正在安全上报脱敏指纹...");
23
+ const result = await (0, immune_reporter_1.reportFingerprints)();
24
+ console.log(result.message);
25
+ break;
26
+ default:
27
+ console.log("用法: npx ts-node src/report.ts [preview|report]");
28
+ console.log(" preview 查看待上报的脱敏错误指纹");
29
+ console.log(" report 执行安全上报");
30
+ }
31
+ }
32
+ main().catch(console.error);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "progmune-runtime",
3
- "version": "2.0.2",
3
+ "version": "2.0.4",
4
4
  "description": "Progmune Runtime — Program Immunology: Constraint-Guided Program Synthesis Runtime",
5
5
  "main": "dist/mcp-server.mjs",
6
6
  "bin": {
package/protocols.json ADDED
@@ -0,0 +1,16 @@
1
+ {
2
+ "verify_password": {
3
+ "pre_states": ["UNAUTHENTICATED"],
4
+ "post_states": ["AUTHENTICATED"]
5
+ },
6
+ "generate_jwt": {
7
+ "pre_states": ["AUTHENTICATED"],
8
+ "post_states": ["TOKEN_ISSUED"],
9
+ "invalidate": ["AUTHENTICATED"]
10
+ },
11
+ "create_session": {
12
+ "pre_states": ["TOKEN_ISSUED"],
13
+ "post_states": ["SESSION_ACTIVE"],
14
+ "invalidate": ["TOKEN_ISSUED"]
15
+ }
16
+ }
@@ -1,55 +0,0 @@
1
- import { Server } from '@modelcontextprotocol/sdk/server/index.js';
2
- import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
3
- import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';
4
- import { createRequire } from 'module';
5
-
6
- const require = createRequire(import.meta.url);
7
- const fs = require('fs');
8
-
9
- const { plan } = require('./planner.js');
10
- const { extractIRPython } = require('./extract-ir-python.js');
11
- const { emitPython } = require('./python-emitter.js');
12
- const { recordRun } = require('./feedback.js');
13
-
14
- async function main() {
15
- const server = new Server({
16
- name: "progmune",
17
- version: "2.0.0"
18
- }, { capabilities: { tools: {} } });
19
-
20
- server.setRequestHandler(ListToolsRequestSchema, async () => ({
21
- tools: [{
22
- name: "generate_verified_code",
23
- description: "生成类型安全的Python代码,仅使用项目中真实存在的函数。",
24
- inputSchema: {
25
- type: "object",
26
- properties: {
27
- intent: { type: "string", description: "编程意图" },
28
- projectPath: { type: "string", description: "项目根目录绝对路径" }
29
- },
30
- required: ["intent", "projectPath"]
31
- }
32
- }]
33
- }));
34
-
35
- server.setRequestHandler(CallToolRequestSchema, async (request) => {
36
- if (request.params.name === "generate_verified_code") {
37
- const { intent, projectPath } = request.params.arguments;
38
- const fns = extractIRPython(projectPath);
39
- fs.writeFileSync("ir.json", JSON.stringify(fns, null, 2));
40
- const actions = await plan(intent);
41
- if (!actions || actions.length === 0) {
42
- return { content: [{ type: "text", text: "无法生成满足约束的代码。" }] };
43
- }
44
- const code = emitPython(actions);
45
- recordRun(intent, actions, true);
46
- return { content: [{ type: "text", text: code }] };
47
- }
48
- throw new Error("未知工具");
49
- });
50
-
51
- const transport = new StdioServerTransport();
52
- await server.connect(transport);
53
- }
54
-
55
- main().catch(console.error);