rfhub-mcp 0.7.0 → 0.8.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/dist/server.js CHANGED
@@ -1,25 +1,27 @@
1
1
  #!/usr/bin/env node
2
+ import packageJson from "../package.json" with { type: "json" };
2
3
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3
4
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
5
  import ArfcnCalculator4G from "./tools/arfcn-calculator-4g.js";
5
6
  import ArfcnCalculator5G from "./tools/arfcn-calculator-5g.js";
6
7
  import ArfcnCalculatorNTN from "./tools/arfcn-calculator-ntn.js";
8
+ import { safeApiPost } from "./utils/request.js";
7
9
  const mcpServer = new McpServer({
8
- name: "rfhub-mcp",
9
- version: "0.6.0",
10
- title: "RFHUB MCP Server",
11
- description: "RFHUB MCP Server",
12
- websiteUrl: "https://rfhub.cn/mcp-server",
10
+ name: packageJson.name,
11
+ version: packageJson.version,
12
+ title: packageJson.title,
13
+ description: packageJson.description,
14
+ websiteUrl: packageJson.websiteUrl,
13
15
  });
14
- new ArfcnCalculator4G(mcpServer).registerAllTools();
15
- new ArfcnCalculator5G(mcpServer).registerAllTools();
16
- new ArfcnCalculatorNTN(mcpServer).registerAllTools();
16
+ ArfcnCalculator4G.registerComputeTool(mcpServer, safeApiPost);
17
+ ArfcnCalculator5G.registerComputeTool(mcpServer, safeApiPost);
18
+ ArfcnCalculatorNTN.registerComputeTool(mcpServer, safeApiPost);
17
19
  async function main() {
18
20
  const transport = new StdioServerTransport();
19
21
  await mcpServer.connect(transport);
20
- console.log("MCP server is running...");
22
+ console.log("rfhub-mcp server is running...");
21
23
  }
22
24
  main().catch((error) => {
23
- console.error("Server error:", error);
25
+ console.error("rfhub-mcp server error:", error);
24
26
  process.exit(1);
25
27
  });
@@ -1,137 +1,131 @@
1
1
  import * as z from "zod/v4";
2
- import { safeApiPost } from "../utils/request.js";
3
2
  import { mcpExResponse } from "../utils/response.js";
4
- export default class ArfcnCalculator4G {
5
- mcpServer;
6
- constructor(mcpServer) {
7
- this.mcpServer = mcpServer;
8
- }
9
- registerAllTools = () => {
10
- this.registerComputeTool();
11
- };
12
- registerComputeTool = () => {
13
- const ModeEnum = z.enum(["n", "f"]);
14
- const DirectionEnum = z.enum(["uplink", "downlink"]);
15
- const DuplexModeEnum = z.enum(["TDD", "FDD"]);
16
- const computeInputSchema = z.object({
17
- Mode: ModeEnum.optional().describe("计算模式,例如 n 表示频点模式,f 表示频率模式"),
18
- DataTransmissionDirection: DirectionEnum.describe("数据传输方向,可选上行(uplink)、下行(downlink)"),
19
- NREF: z.number().int().optional().describe('频点参考(NREF),例如 504999。用于在频点模式(Mode=`"n"`)下确定中心频率。'),
20
- FREF: z.number().optional().describe('频率参考(FREF),单位为 MHz,例如 3500.0。用于在频率模式(Mode=`"f"`)下直接指定中心频率。'),
21
- Band: z.string().optional().describe('频段标识符,例如 "b3"、"b41" 等'),
22
- Bandwidth: z.number().positive().optional().describe("信道带宽,单位为 MHz,例如 100 表示 100MHz"),
23
- });
24
- const computeOutputSchema = z.object({
25
- Mode: ModeEnum.nullable().optional(),
26
- Mode_Error: z.string().nullable().optional(),
27
- DataTransmissionDirection: DirectionEnum.nullable().optional(),
28
- DataTransmissionDirection_Error: z.string().nullable().optional(),
29
- NREF: z.number().int().nullable().optional(),
30
- NREF_Error: z.string().nullable().optional(),
31
- FREF: z.number().nullable().optional(),
32
- FREF_Error: z.string().nullable().optional(),
33
- BandOptions: z.array(z.string()).nullable().optional(),
34
- BandOptions_Error: z.string().nullable().optional(),
35
- Band: z.string().nullable().optional(),
36
- Band_Error: z.string().nullable().optional(),
37
- FREF_Low: z.number().nullable().optional(),
38
- FREF_High: z.number().nullable().optional(),
39
- NREF_First: z.number().int().nullable().optional(),
40
- NREF_Last: z.number().int().nullable().optional(),
41
- DuplexMode: DuplexModeEnum.nullable().optional(),
42
- SCS: z.string().nullable().optional(),
43
- BandwidthOptions: z.array(z.string()).nullable().optional(),
44
- BandwidthOptions_Error: z.string().nullable().optional(),
45
- Bandwidth: z.number().nullable().optional(),
46
- Bandwidth_Error: z.string().nullable().optional(),
47
- NRB: z.number().int().nullable().optional(),
48
- FREF_AvailableLow: z.number().nullable().optional(),
49
- FREF_AvailableHigh: z.number().nullable().optional(),
50
- });
51
- const apiResultSchema = z.object({
52
- Mode: z.string().nullable().optional(),
53
- Mode_Error: z.string().nullable().optional(),
54
- DataTransmissionDirection: z.string().nullable().optional(),
55
- DataTransmissionDirection_Error: z.string().nullable().optional(),
56
- NREF: z.string().nullable().optional(),
57
- NREF_Error: z.string().nullable().optional(),
58
- FREF: z.string().nullable().optional(),
59
- FREF_Error: z.string().nullable().optional(),
60
- BandOptions: z.array(z.string()).nullable().optional(),
61
- BandOptions_Error: z.string().nullable().optional(),
62
- Band: z.string().nullable().optional(),
63
- Band_Error: z.string().nullable().optional(),
64
- FREF_Low: z.string().nullable().optional(),
65
- FREF_High: z.string().nullable().optional(),
66
- NREF_First: z.string().nullable().optional(),
67
- NREF_Last: z.string().nullable().optional(),
68
- DuplexMode: DuplexModeEnum.nullable().optional(),
69
- SCS: z.string().nullable().optional(),
70
- BandwidthOptions: z.array(z.string()).nullable().optional(),
71
- BandwidthOptions_Error: z.string().nullable().optional(),
72
- Bandwidth: z.string().nullable().optional(),
73
- Bandwidth_Error: z.string().nullable().optional(),
74
- NRB: z.string().nullable().optional(),
75
- FREF_AvailableLow: z.string().nullable().optional(),
76
- FREF_AvailableHigh: z.string().nullable().optional(),
77
- });
78
- this.mcpServer.registerTool("arfcn_calculator_4g_compute", {
79
- title: "4G/LTE频点频率转换与对应频带信息",
80
- description: "支持4G LTE网络中频率与频点之间的相互转换,并附带特定频段的详细信息展示",
81
- inputSchema: computeInputSchema,
82
- outputSchema: computeOutputSchema,
83
- }, async (input) => {
84
- try {
85
- const apiRequest = {
86
- Mode: input.Mode ?? (input.NREF && "n"),
87
- DataTransmissionDirection: input.DataTransmissionDirection,
88
- Band: input.Band?.replaceAll("b", "").replaceAll("B", "") ?? null,
89
- NERF: input.NREF?.toString() ?? null,
90
- FERF: input.FREF?.toString() ?? null,
91
- Bandwidth: input.Bandwidth?.toString() ?? null,
92
- };
93
- const result = await safeApiPost("/api/arfcn-calculator-4g/compute", apiRequest);
94
- const apiResult = apiResultSchema.parse(result);
95
- const structuredContent = {
96
- Mode: apiResult.Mode ?? null,
97
- Mode_Error: apiResult.Mode_Error ?? null,
98
- DataTransmissionDirection: apiResult.DataTransmissionDirection ?? null,
99
- DataTransmissionDirection_Error: apiResult.DataTransmissionDirection_Error ?? null,
100
- NREF: apiResult.NREF ?? null,
101
- NREF_Error: apiResult.NREF_Error ?? null,
102
- FREF: apiResult.FREF ?? null,
103
- FREF_Error: apiResult.FREF_Error ?? null,
104
- BandOptions: apiResult.BandOptions ?? null,
105
- BandOptions_Error: apiResult.BandOptions_Error ?? null,
106
- Band: apiResult.Band ?? null,
107
- Band_Error: apiResult.Band_Error ?? null,
108
- FREF_Low: apiResult.FREF_Low ?? null,
109
- FREF_High: apiResult.FREF_High ?? null,
110
- NREF_First: apiResult.NREF_First ?? null,
111
- NREF_Last: apiResult.NREF_Last ?? null,
112
- DuplexMode: apiResult.DuplexMode ?? null,
113
- SCS: apiResult.SCS ?? null,
114
- BandwidthOptions: apiResult.BandwidthOptions ?? null,
115
- BandwidthOptions_Error: apiResult.BandwidthOptions_Error ?? null,
116
- Bandwidth: apiResult.Bandwidth ?? null,
117
- Bandwidth_Error: apiResult.Bandwidth_Error ?? null,
118
- NRB: apiResult.NRB ?? null,
119
- FREF_AvailableLow: apiResult.FREF_AvailableLow ?? null,
120
- FREF_AvailableHigh: apiResult.FREF_AvailableHigh ?? null,
121
- };
122
- return {
123
- content: [
124
- {
125
- type: "text",
126
- text: JSON.stringify(structuredContent, null, 2),
127
- },
128
- ],
129
- structuredContent,
130
- };
131
- }
132
- catch {
133
- return mcpExResponse;
134
- }
135
- });
136
- };
137
- }
3
+ export const registerComputeTool = (mcpServer, getResult) => {
4
+ const ModeEnum = z.enum(["n", "f"]);
5
+ const DirectionEnum = z.enum(["uplink", "downlink"]);
6
+ const DuplexModeEnum = z.enum(["TDD", "FDD"]);
7
+ const computeInputSchema = z.object({
8
+ Mode: ModeEnum.optional().describe("计算模式,例如 n 表示频点模式,f 表示频率模式"),
9
+ DataTransmissionDirection: DirectionEnum.describe("数据传输方向,可选上行(uplink)、下行(downlink)"),
10
+ NREF: z.number().int().optional().describe('频点参考(NREF),例如 504999。用于在频点模式(Mode=`"n"`)下确定中心频率。'),
11
+ FREF: z.number().optional().describe('频率参考(FREF),单位为 MHz,例如 3500.0。用于在频率模式(Mode=`"f"`)下直接指定中心频率。'),
12
+ Band: z.string().optional().describe('频段标识符,例如 "b3""b41" 等'),
13
+ Bandwidth: z.number().positive().optional().describe("信道带宽,单位为 MHz,例如 100 表示 100MHz"),
14
+ });
15
+ const computeOutputSchema = z.object({
16
+ Mode: ModeEnum.nullable().optional(),
17
+ Mode_Error: z.string().nullable().optional(),
18
+ DataTransmissionDirection: DirectionEnum.nullable().optional(),
19
+ DataTransmissionDirection_Error: z.string().nullable().optional(),
20
+ NREF: z.number().int().nullable().optional(),
21
+ NREF_Error: z.string().nullable().optional(),
22
+ FREF: z.number().nullable().optional(),
23
+ FREF_Error: z.string().nullable().optional(),
24
+ BandOptions: z.array(z.string()).nullable().optional(),
25
+ BandOptions_Error: z.string().nullable().optional(),
26
+ Band: z.string().nullable().optional(),
27
+ Band_Error: z.string().nullable().optional(),
28
+ FREF_Low: z.number().nullable().optional(),
29
+ FREF_High: z.number().nullable().optional(),
30
+ NREF_First: z.number().int().nullable().optional(),
31
+ NREF_Last: z.number().int().nullable().optional(),
32
+ DuplexMode: DuplexModeEnum.nullable().optional(),
33
+ SCS: z.string().nullable().optional(),
34
+ BandwidthOptions: z.array(z.string()).nullable().optional(),
35
+ BandwidthOptions_Error: z.string().nullable().optional(),
36
+ Bandwidth: z.number().nullable().optional(),
37
+ Bandwidth_Error: z.string().nullable().optional(),
38
+ NRB: z.number().int().nullable().optional(),
39
+ FREF_AvailableLow: z.number().nullable().optional(),
40
+ FREF_AvailableHigh: z.number().nullable().optional(),
41
+ });
42
+ const apiResultSchema = z.object({
43
+ Mode: z.string().nullable().optional(),
44
+ Mode_Error: z.string().nullable().optional(),
45
+ DataTransmissionDirection: z.string().nullable().optional(),
46
+ DataTransmissionDirection_Error: z.string().nullable().optional(),
47
+ NREF: z.string().nullable().optional(),
48
+ NREF_Error: z.string().nullable().optional(),
49
+ FREF: z.string().nullable().optional(),
50
+ FREF_Error: z.string().nullable().optional(),
51
+ BandOptions: z.array(z.string()).nullable().optional(),
52
+ BandOptions_Error: z.string().nullable().optional(),
53
+ Band: z.string().nullable().optional(),
54
+ Band_Error: z.string().nullable().optional(),
55
+ FREF_Low: z.string().nullable().optional(),
56
+ FREF_High: z.string().nullable().optional(),
57
+ NREF_First: z.string().nullable().optional(),
58
+ NREF_Last: z.string().nullable().optional(),
59
+ DuplexMode: DuplexModeEnum.nullable().optional(),
60
+ SCS: z.string().nullable().optional(),
61
+ BandwidthOptions: z.array(z.string()).nullable().optional(),
62
+ BandwidthOptions_Error: z.string().nullable().optional(),
63
+ Bandwidth: z.string().nullable().optional(),
64
+ Bandwidth_Error: z.string().nullable().optional(),
65
+ NRB: z.string().nullable().optional(),
66
+ FREF_AvailableLow: z.string().nullable().optional(),
67
+ FREF_AvailableHigh: z.string().nullable().optional(),
68
+ });
69
+ mcpServer.registerTool("arfcn_calculator_4g_compute", {
70
+ title: "4G/LTE频点频率转换与对应频带信息",
71
+ description: "支持4G LTE网络中频率与频点之间的相互转换,并附带特定频段的详细信息展示",
72
+ inputSchema: computeInputSchema,
73
+ outputSchema: computeOutputSchema,
74
+ }, async (input) => {
75
+ try {
76
+ const apiRequest = {
77
+ Mode: input.Mode ?? (input.NREF && "n"),
78
+ DataTransmissionDirection: input.DataTransmissionDirection,
79
+ Band: input.Band?.replaceAll("b", "").replaceAll("B", "") ?? null,
80
+ NERF: input.NREF?.toString() ?? null,
81
+ FERF: input.FREF?.toString() ?? null,
82
+ Bandwidth: input.Bandwidth?.toString() ?? null,
83
+ };
84
+ const result = await getResult("/api/arfcn-calculator-4g/compute", apiRequest);
85
+ // const result = await safeApiPost("/api/arfcn-calculator-4g/compute", apiRequest);
86
+ const apiResult = apiResultSchema.parse(result);
87
+ const structuredContent = {
88
+ Mode: apiResult.Mode ?? null,
89
+ Mode_Error: apiResult.Mode_Error ?? null,
90
+ DataTransmissionDirection: apiResult.DataTransmissionDirection ?? null,
91
+ DataTransmissionDirection_Error: apiResult.DataTransmissionDirection_Error ?? null,
92
+ NREF: apiResult.NREF ?? null,
93
+ NREF_Error: apiResult.NREF_Error ?? null,
94
+ FREF: apiResult.FREF ?? null,
95
+ FREF_Error: apiResult.FREF_Error ?? null,
96
+ BandOptions: apiResult.BandOptions ?? null,
97
+ BandOptions_Error: apiResult.BandOptions_Error ?? null,
98
+ Band: apiResult.Band ?? null,
99
+ Band_Error: apiResult.Band_Error ?? null,
100
+ FREF_Low: apiResult.FREF_Low ?? null,
101
+ FREF_High: apiResult.FREF_High ?? null,
102
+ NREF_First: apiResult.NREF_First ?? null,
103
+ NREF_Last: apiResult.NREF_Last ?? null,
104
+ DuplexMode: apiResult.DuplexMode ?? null,
105
+ SCS: apiResult.SCS ?? null,
106
+ BandwidthOptions: apiResult.BandwidthOptions ?? null,
107
+ BandwidthOptions_Error: apiResult.BandwidthOptions_Error ?? null,
108
+ Bandwidth: apiResult.Bandwidth ?? null,
109
+ Bandwidth_Error: apiResult.Bandwidth_Error ?? null,
110
+ NRB: apiResult.NRB ?? null,
111
+ FREF_AvailableLow: apiResult.FREF_AvailableLow ?? null,
112
+ FREF_AvailableHigh: apiResult.FREF_AvailableHigh ?? null,
113
+ };
114
+ return {
115
+ content: [
116
+ {
117
+ type: "text",
118
+ text: JSON.stringify(structuredContent, null, 2),
119
+ },
120
+ ],
121
+ structuredContent,
122
+ };
123
+ }
124
+ catch {
125
+ return mcpExResponse;
126
+ }
127
+ });
128
+ };
129
+ export default {
130
+ registerComputeTool,
131
+ };
@@ -1,207 +1,200 @@
1
1
  import * as z from "zod/v4";
2
- import { safeApiPost } from "../utils/request.js";
3
2
  import { mcpExResponse } from "../utils/response.js";
4
- export default class ArfcnCalculator5G {
5
- mcpServer;
6
- constructor(mcpServer) {
7
- this.mcpServer = mcpServer;
8
- }
9
- registerAllTools = () => {
10
- this.registerComputeTool();
11
- };
12
- registerComputeTool = () => {
13
- const ModeEnum = z.enum(["n", "f"]);
14
- const DirectionEnum = z.enum(["uplink", "downlink"]);
15
- const DuplexModeEnum = z.enum(["TDD", "FDD"]);
16
- const computeInputSchema = z.object({
17
- Mode: ModeEnum.nullable().optional().describe("计算模式,例如 n 表示频点模式,f 表示频率模式"),
18
- DataTransmissionDirection: DirectionEnum.describe("数据传输方向,可选上行(uplink)、下行(downlink)"),
19
- NREF: z.number().int().nullable().optional().describe('频点参考值(NREF),例如 `"504999"`。用于在频点模式(Mode=`"n"`)下确定中心频率。'),
20
- FREF: z.number().nullable().optional().describe('频率参考值(FREF),例如 `"3500.0"`。用于在频率模式(Mode=`"f"`)下直接指定中心频率。'),
21
- Band: z.string().nullable().optional().describe('频段标识符,例如 `"n78"`、`"n41"` 等。用于确定频段的上下行配置、信道栅格(raster)及边界频率。'),
22
- FRaster: z.number().int().nullable().optional().describe("频率栅格(Frequency Raster),单位为 kHz,例如 5、15。用于频点与频率之间的转换计算。"),
23
- SCS: z.number().int().nullable().optional().describe("子载波间隔(Subcarrier Spacing),单位为 kHz,例如 15、30。影响资源块结构和带宽计算。"),
24
- Bandwidth: z
25
- .number()
26
- .nullable()
27
- .optional()
28
- .describe("信道带宽(Channel Bandwidth),单位为 MHz,例如 5、20、100。用于确定传输带宽配置(Transmission Bandwidth Configuration)。"),
29
- SSBlockSCS: z.number().int().nullable().optional().describe("SSB(Synchronization Signal Block)的子载波间隔,单位为 kHz,例如 15、30。"),
30
- SSBlockPattern: z
31
- .string()
32
- .nullable()
33
- .optional()
34
- .describe('SSB 波束扫描图案类型,例如 `"Case A"`、`"Case B"`、`"Case C"`(FR1)或 `"Case D"`、`"Case E"`(FR2),影响 SSB 时域位置和数量。'),
35
- GSCN: z
36
- .number()
37
- .int()
38
- .nullable()
39
- .optional()
40
- .describe("全局同步信道号(Global Synchronization Channel Number),用于粗粒度频率搜索,特别是在非服务小区初始接入时。例如 504990"),
41
- SSREF: z.number().nullable().optional().describe("SSB 中心频率对应的参考频率(单位:Hz 或 MHz,依上下文而定),常用于从 GSCN 或 SSB 配置反推绝对频率。"),
42
- N: z.number().int().nullable().optional().describe("用于 SSB 频域位置计算的参数 N,通常与 GSCN 或 raster 相关。例如 6312"),
43
- M: z.number().int().nullable().optional().describe("SSB 频域偏移步长因子,取决于频段和 SSB 子载波间隔。例如 1、3、5"),
44
- });
45
- const computeOutputSchema = z.object({
46
- Mode: ModeEnum.nullable().optional(),
47
- Mode_Error: z.string().nullable().optional(),
48
- DataTransmissionDirection: DirectionEnum.nullable().optional(),
49
- DataTransmissionDirection_Error: z.string().nullable().optional(),
50
- NREF: z.number().int().nullable().optional(),
51
- NREF_Error: z.string().nullable().optional(),
52
- FREF: z.number().nullable().optional(),
53
- FREF_Error: z.string().nullable().optional(),
54
- FGlobalRaster: z.number().nullable().optional(), // 全局频率栅格,kHz(数值)
55
- FrequencyRangeDesignation: z.string().nullable().optional(), // 频率范围标识符
56
- BandOptions: z.array(z.string()).nullable().optional(),
57
- BandOptions_Error: z.string().nullable().optional(),
58
- Band: z.string().nullable().optional(),
59
- Band_Error: z.string().nullable().optional(),
60
- FREF_Low: z.number().nullable().optional(),
61
- FREF_High: z.number().nullable().optional(),
62
- FRasterOptions_Error: z.string().nullable().optional(),
63
- FRasterOptions: z.array(z.string()).nullable().optional(),
64
- FRaster: z.number().nullable().optional(),
65
- FRaster_Error: z.string().nullable().optional(),
66
- NREF_StepSize: z.number().int().nullable().optional(),
67
- NREF_First: z.number().int().nullable().optional(),
68
- NREF_Last: z.number().int().nullable().optional(),
69
- DuplexMode: DuplexModeEnum.nullable().optional(),
70
- SCSOptions: z.array(z.string()).nullable().optional(),
71
- SCSOptions_Error: z.string().nullable().optional(),
72
- SCS: z.string().nullable().optional(),
73
- SCS_Error: z.string().nullable().optional(),
74
- BandwidthOptions: z.array(z.string()).nullable().optional(),
75
- BandwidthOptions_Error: z.string().nullable().optional(),
76
- Bandwidth: z.number().nullable().optional(), // 带宽单位可能是 MHz,但以数字形式
77
- Bandwidth_Error: z.string().nullable().optional(),
78
- NRB: z.number().int().nullable().optional(), // 资源块数量,整数
79
- MinimumGuardband: z.number().nullable().optional(), // 最小保护带宽,kHz(数值)
80
- FREF_AvailableLow: z.number().nullable().optional(),
81
- FREF_AvailableHigh: z.number().nullable().optional(),
82
- SSBlockSCSOptions: z.array(z.number()).nullable().optional(),
83
- SSBlockSCSOptions_Error: z.string().nullable().optional(),
84
- SSBlockSCS: z.number().nullable().optional(),
85
- SSBlockSCS_Error: z.string().nullable().optional(),
86
- SSBlockPatternOptions: z.array(z.string()).nullable().optional(),
87
- SSBlockPatternOptions_Error: z.string().nullable().optional(),
88
- SSBlockPattern: z.string().nullable().optional(),
89
- SSBlockPattern_Error: z.string().nullable().optional(),
90
- NRaster: z.number().nullable().optional(),
91
- GSCN_First: z.number().int().nullable().optional(),
92
- GSCN_Last: z.number().int().nullable().optional(),
93
- GSCN_StepSize: z.number().int().nullable().optional(),
94
- GSCN: z.number().int().nullable().optional(),
95
- GSCN_Error: z.string().nullable().optional(),
96
- SSREF: z.number().nullable().optional(),
97
- SSREF_Error: z.string().nullable().optional(),
98
- SSBlockNREF: z.number().int().nullable().optional(),
99
- N: z.number().int().nullable().optional(),
100
- N_Error: z.string().nullable().optional(),
101
- MOptions: z.array(z.number()).nullable().optional(),
102
- MOptions_Error: z.string().nullable().optional(),
103
- M: z.number().int().nullable().optional(),
104
- M_Error: z.string().nullable().optional(),
105
- });
106
- const apiResultSchema = z.object({
107
- Mode: ModeEnum.nullable().optional(),
108
- Mode_Error: z.string().nullable().optional(),
109
- DataTransmissionDirection: DirectionEnum.nullable().optional(),
110
- DataTransmissionDirection_Error: z.string().nullable().optional(),
111
- NREF: z.string().nullable().optional(),
112
- NREF_Error: z.string().nullable().optional(),
113
- FREF: z.string().nullable().optional(),
114
- FREF_Error: z.string().nullable().optional(),
115
- FGlobalRaster: z.string().nullable().optional(), // 全局频率栅格,kHz
116
- FrequencyRangeDesignation: z.string().nullable().optional(), // 频率范围标识符
117
- BandOptions: z.array(z.string()).nullable().optional(),
118
- BandOptions_Error: z.string().nullable().optional(),
119
- Band: z.string().nullable().optional(),
120
- Band_Error: z.string().nullable().optional(),
121
- FREF_Low: z.string().nullable().optional(),
122
- FREF_High: z.string().nullable().optional(),
123
- FRasterOptions_Error: z.string().nullable().optional(),
124
- FRasterOptions: z.array(z.string()).nullable().optional(),
125
- FRaster: z.string().nullable().optional(),
126
- FRaster_Error: z.string().nullable().optional(),
127
- NREF_StepSize: z.string().nullable().optional(),
128
- NREF_First: z.string().nullable().optional(),
129
- NREF_Last: z.string().nullable().optional(),
130
- DuplexMode: DuplexModeEnum.nullable().optional(),
131
- SCSOptions: z.array(z.string()).nullable().optional(),
132
- SCSOptions_Error: z.string().nullable().optional(),
133
- SCS: z.string().nullable().optional(),
134
- SCS_Error: z.string().nullable().optional(),
135
- BandwidthOptions: z.array(z.string()).nullable().optional(),
136
- BandwidthOptions_Error: z.string().nullable().optional(),
137
- Bandwidth: z.string().nullable().optional(),
138
- Bandwidth_Error: z.string().nullable().optional(),
139
- NRB: z.string().nullable().optional(),
140
- MinimumGuardband: z.string().nullable().optional(),
141
- FREF_AvailableLow: z.string().nullable().optional(),
142
- FREF_AvailableHigh: z.string().nullable().optional(),
143
- SSBlockSCSOptions: z.array(z.string()).nullable().optional(),
144
- SSBlockSCSOptions_Error: z.string().nullable().optional(),
145
- SSBlockSCS: z.string().nullable().optional(),
146
- SSBlockSCS_Error: z.string().nullable().optional(),
147
- SSBlockPatternOptions: z.array(z.string()).nullable().optional(),
148
- SSBlockPatternOptions_Error: z.string().nullable().optional(),
149
- SSBlockPattern: z.string().nullable().optional(),
150
- SSBlockPattern_Error: z.string().nullable().optional(),
151
- NRaster: z.string().nullable().optional(),
152
- GSCN_First: z.string().nullable().optional(),
153
- GSCN_Last: z.string().nullable().optional(),
154
- GSCN_StepSize: z.string().nullable().optional(),
155
- GSCN: z.string().nullable().optional(),
156
- GSCN_Error: z.string().nullable().optional(),
157
- SSREF: z.string().nullable().optional(),
158
- SSREF_Error: z.string().nullable().optional(),
159
- SSBlockNREF: z.string().nullable().optional(),
160
- N: z.string().nullable().optional(),
161
- N_Error: z.string().nullable().optional(),
162
- MOptions: z.array(z.string()).nullable().optional(),
163
- MOptions_Error: z.string().nullable().optional(),
164
- M: z.string().nullable().optional(),
165
- M_Error: z.string().nullable().optional(),
166
- });
167
- this.mcpServer.registerTool("arfcn_calculator_5g_compute", {
168
- title: "5G/NR频点频率转换与对应频带信息",
169
- description: "支持5G NR网络中频率与频点之间的相互转换,并附带特定频段的详细信息展示",
170
- inputSchema: computeInputSchema,
171
- outputSchema: computeOutputSchema,
172
- }, async (input) => {
173
- try {
174
- const apiRequest = {
175
- Mode: input.Mode ?? (input.NREF && "n"),
176
- DataTransmissionDirection: input.DataTransmissionDirection,
177
- Band: input.Band?.replaceAll("b", "").replaceAll("B", "") ?? null,
178
- NERF: input.NREF?.toString() ?? null,
179
- FERF: input.FREF?.toString() ?? null,
180
- Bandwidth: input.Bandwidth?.toString() ?? null,
181
- FRaster: input.FRaster?.toString() ?? null,
182
- SCS: input.SCS?.toString() ?? null,
183
- SSBlockSCS: input.SSBlockSCS?.toString() ?? null,
184
- GSCN: input.GSCN?.toString() ?? null,
185
- SSREF: input.SSREF?.toString() ?? null,
186
- SSBlockPattern: input.SSBlockPattern?.toString() ?? null,
187
- N: input.N?.toString() ?? null,
188
- M: input.M?.toString() ?? null,
189
- };
190
- const result = await safeApiPost("/api/arfcn-calculator-5g/compute", apiRequest);
191
- const apiResult = apiResultSchema.parse(result);
192
- return {
193
- content: [
194
- {
195
- type: "text",
196
- text: JSON.stringify(apiResult, null, 2),
197
- },
198
- ],
199
- structuredContent: apiResult,
200
- };
201
- }
202
- catch {
203
- return mcpExResponse;
204
- }
205
- });
206
- };
207
- }
3
+ const registerComputeTool = (mcpServer, getResult) => {
4
+ const ModeEnum = z.enum(["n", "f"]);
5
+ const DirectionEnum = z.enum(["uplink", "downlink"]);
6
+ const DuplexModeEnum = z.enum(["TDD", "FDD"]);
7
+ const computeInputSchema = z.object({
8
+ Mode: ModeEnum.nullable().optional().describe("计算模式,例如 n 表示频点模式,f 表示频率模式"),
9
+ DataTransmissionDirection: DirectionEnum.describe("数据传输方向,可选上行(uplink)、下行(downlink)"),
10
+ NREF: z.number().int().nullable().optional().describe('频点参考值(NREF),例如 `"504999"`。用于在频点模式(Mode=`"n"`)下确定中心频率。'),
11
+ FREF: z.number().nullable().optional().describe('频率参考值(FREF),例如 `"3500.0"`。用于在频率模式(Mode=`"f"`)下直接指定中心频率。'),
12
+ Band: z.string().nullable().optional().describe('频段标识符,例如 `"n78"`、`"n41"` 等。用于确定频段的上下行配置、信道栅格(raster)及边界频率。'),
13
+ FRaster: z.number().int().nullable().optional().describe("频率栅格(Frequency Raster),单位为 kHz,例如 5、15。用于频点与频率之间的转换计算。"),
14
+ SCS: z.number().int().nullable().optional().describe("子载波间隔(Subcarrier Spacing),单位为 kHz,例如 15、30。影响资源块结构和带宽计算。"),
15
+ Bandwidth: z
16
+ .number()
17
+ .nullable()
18
+ .optional()
19
+ .describe("信道带宽(Channel Bandwidth),单位为 MHz,例如 5、20、100。用于确定传输带宽配置(Transmission Bandwidth Configuration)。"),
20
+ SSBlockSCS: z.number().int().nullable().optional().describe("SSB(Synchronization Signal Block)的子载波间隔,单位为 kHz,例如 15、30。"),
21
+ SSBlockPattern: z
22
+ .string()
23
+ .nullable()
24
+ .optional()
25
+ .describe('SSB 波束扫描图案类型,例如 `"Case A"`、`"Case B"`、`"Case C"`(FR1)或 `"Case D"`、`"Case E"`(FR2),影响 SSB 时域位置和数量。'),
26
+ GSCN: z
27
+ .number()
28
+ .int()
29
+ .nullable()
30
+ .optional()
31
+ .describe("全局同步信道号(Global Synchronization Channel Number),用于粗粒度频率搜索,特别是在非服务小区初始接入时。例如 504990"),
32
+ SSREF: z.number().nullable().optional().describe("SSB 中心频率对应的参考频率(单位:Hz 或 MHz,依上下文而定),常用于从 GSCN 或 SSB 配置反推绝对频率。"),
33
+ N: z.number().int().nullable().optional().describe("用于 SSB 频域位置计算的参数 N,通常与 GSCN raster 相关。例如 6312"),
34
+ M: z.number().int().nullable().optional().describe("SSB 频域偏移步长因子,取决于频段和 SSB 子载波间隔。例如 1、3、5"),
35
+ });
36
+ const computeOutputSchema = z.object({
37
+ Mode: ModeEnum.nullable().optional(),
38
+ Mode_Error: z.string().nullable().optional(),
39
+ DataTransmissionDirection: DirectionEnum.nullable().optional(),
40
+ DataTransmissionDirection_Error: z.string().nullable().optional(),
41
+ NREF: z.number().int().nullable().optional(),
42
+ NREF_Error: z.string().nullable().optional(),
43
+ FREF: z.number().nullable().optional(),
44
+ FREF_Error: z.string().nullable().optional(),
45
+ FGlobalRaster: z.number().nullable().optional(), // 全局频率栅格,kHz(数值)
46
+ FrequencyRangeDesignation: z.string().nullable().optional(), // 频率范围标识符
47
+ BandOptions: z.array(z.string()).nullable().optional(),
48
+ BandOptions_Error: z.string().nullable().optional(),
49
+ Band: z.string().nullable().optional(),
50
+ Band_Error: z.string().nullable().optional(),
51
+ FREF_Low: z.number().nullable().optional(),
52
+ FREF_High: z.number().nullable().optional(),
53
+ FRasterOptions_Error: z.string().nullable().optional(),
54
+ FRasterOptions: z.array(z.string()).nullable().optional(),
55
+ FRaster: z.number().nullable().optional(),
56
+ FRaster_Error: z.string().nullable().optional(),
57
+ NREF_StepSize: z.number().int().nullable().optional(),
58
+ NREF_First: z.number().int().nullable().optional(),
59
+ NREF_Last: z.number().int().nullable().optional(),
60
+ DuplexMode: DuplexModeEnum.nullable().optional(),
61
+ SCSOptions: z.array(z.string()).nullable().optional(),
62
+ SCSOptions_Error: z.string().nullable().optional(),
63
+ SCS: z.string().nullable().optional(),
64
+ SCS_Error: z.string().nullable().optional(),
65
+ BandwidthOptions: z.array(z.string()).nullable().optional(),
66
+ BandwidthOptions_Error: z.string().nullable().optional(),
67
+ Bandwidth: z.number().nullable().optional(), // 带宽单位可能是 MHz,但以数字形式
68
+ Bandwidth_Error: z.string().nullable().optional(),
69
+ NRB: z.number().int().nullable().optional(), // 资源块数量,整数
70
+ MinimumGuardband: z.number().nullable().optional(), // 最小保护带宽,kHz(数值)
71
+ FREF_AvailableLow: z.number().nullable().optional(),
72
+ FREF_AvailableHigh: z.number().nullable().optional(),
73
+ SSBlockSCSOptions: z.array(z.number()).nullable().optional(),
74
+ SSBlockSCSOptions_Error: z.string().nullable().optional(),
75
+ SSBlockSCS: z.number().nullable().optional(),
76
+ SSBlockSCS_Error: z.string().nullable().optional(),
77
+ SSBlockPatternOptions: z.array(z.string()).nullable().optional(),
78
+ SSBlockPatternOptions_Error: z.string().nullable().optional(),
79
+ SSBlockPattern: z.string().nullable().optional(),
80
+ SSBlockPattern_Error: z.string().nullable().optional(),
81
+ NRaster: z.number().nullable().optional(),
82
+ GSCN_First: z.number().int().nullable().optional(),
83
+ GSCN_Last: z.number().int().nullable().optional(),
84
+ GSCN_StepSize: z.number().int().nullable().optional(),
85
+ GSCN: z.number().int().nullable().optional(),
86
+ GSCN_Error: z.string().nullable().optional(),
87
+ SSREF: z.number().nullable().optional(),
88
+ SSREF_Error: z.string().nullable().optional(),
89
+ SSBlockNREF: z.number().int().nullable().optional(),
90
+ N: z.number().int().nullable().optional(),
91
+ N_Error: z.string().nullable().optional(),
92
+ MOptions: z.array(z.number()).nullable().optional(),
93
+ MOptions_Error: z.string().nullable().optional(),
94
+ M: z.number().int().nullable().optional(),
95
+ M_Error: z.string().nullable().optional(),
96
+ });
97
+ const apiResultSchema = z.object({
98
+ Mode: ModeEnum.nullable().optional(),
99
+ Mode_Error: z.string().nullable().optional(),
100
+ DataTransmissionDirection: DirectionEnum.nullable().optional(),
101
+ DataTransmissionDirection_Error: z.string().nullable().optional(),
102
+ NREF: z.string().nullable().optional(),
103
+ NREF_Error: z.string().nullable().optional(),
104
+ FREF: z.string().nullable().optional(),
105
+ FREF_Error: z.string().nullable().optional(),
106
+ FGlobalRaster: z.string().nullable().optional(), // 全局频率栅格,kHz
107
+ FrequencyRangeDesignation: z.string().nullable().optional(), // 频率范围标识符
108
+ BandOptions: z.array(z.string()).nullable().optional(),
109
+ BandOptions_Error: z.string().nullable().optional(),
110
+ Band: z.string().nullable().optional(),
111
+ Band_Error: z.string().nullable().optional(),
112
+ FREF_Low: z.string().nullable().optional(),
113
+ FREF_High: z.string().nullable().optional(),
114
+ FRasterOptions_Error: z.string().nullable().optional(),
115
+ FRasterOptions: z.array(z.string()).nullable().optional(),
116
+ FRaster: z.string().nullable().optional(),
117
+ FRaster_Error: z.string().nullable().optional(),
118
+ NREF_StepSize: z.string().nullable().optional(),
119
+ NREF_First: z.string().nullable().optional(),
120
+ NREF_Last: z.string().nullable().optional(),
121
+ DuplexMode: DuplexModeEnum.nullable().optional(),
122
+ SCSOptions: z.array(z.string()).nullable().optional(),
123
+ SCSOptions_Error: z.string().nullable().optional(),
124
+ SCS: z.string().nullable().optional(),
125
+ SCS_Error: z.string().nullable().optional(),
126
+ BandwidthOptions: z.array(z.string()).nullable().optional(),
127
+ BandwidthOptions_Error: z.string().nullable().optional(),
128
+ Bandwidth: z.string().nullable().optional(),
129
+ Bandwidth_Error: z.string().nullable().optional(),
130
+ NRB: z.string().nullable().optional(),
131
+ MinimumGuardband: z.string().nullable().optional(),
132
+ FREF_AvailableLow: z.string().nullable().optional(),
133
+ FREF_AvailableHigh: z.string().nullable().optional(),
134
+ SSBlockSCSOptions: z.array(z.string()).nullable().optional(),
135
+ SSBlockSCSOptions_Error: z.string().nullable().optional(),
136
+ SSBlockSCS: z.string().nullable().optional(),
137
+ SSBlockSCS_Error: z.string().nullable().optional(),
138
+ SSBlockPatternOptions: z.array(z.string()).nullable().optional(),
139
+ SSBlockPatternOptions_Error: z.string().nullable().optional(),
140
+ SSBlockPattern: z.string().nullable().optional(),
141
+ SSBlockPattern_Error: z.string().nullable().optional(),
142
+ NRaster: z.string().nullable().optional(),
143
+ GSCN_First: z.string().nullable().optional(),
144
+ GSCN_Last: z.string().nullable().optional(),
145
+ GSCN_StepSize: z.string().nullable().optional(),
146
+ GSCN: z.string().nullable().optional(),
147
+ GSCN_Error: z.string().nullable().optional(),
148
+ SSREF: z.string().nullable().optional(),
149
+ SSREF_Error: z.string().nullable().optional(),
150
+ SSBlockNREF: z.string().nullable().optional(),
151
+ N: z.string().nullable().optional(),
152
+ N_Error: z.string().nullable().optional(),
153
+ MOptions: z.array(z.string()).nullable().optional(),
154
+ MOptions_Error: z.string().nullable().optional(),
155
+ M: z.string().nullable().optional(),
156
+ M_Error: z.string().nullable().optional(),
157
+ });
158
+ mcpServer.registerTool("arfcn_calculator_5g_compute", {
159
+ title: "5G/NR频点频率转换与对应频带信息",
160
+ description: "支持5G NR网络中频率与频点之间的相互转换,并附带特定频段的详细信息展示",
161
+ inputSchema: computeInputSchema,
162
+ outputSchema: computeOutputSchema,
163
+ }, async (input) => {
164
+ try {
165
+ const apiRequest = {
166
+ Mode: input.Mode ?? (input.NREF && "n"),
167
+ DataTransmissionDirection: input.DataTransmissionDirection,
168
+ Band: input.Band?.replaceAll("b", "").replaceAll("B", "") ?? null,
169
+ NERF: input.NREF?.toString() ?? null,
170
+ FERF: input.FREF?.toString() ?? null,
171
+ Bandwidth: input.Bandwidth?.toString() ?? null,
172
+ FRaster: input.FRaster?.toString() ?? null,
173
+ SCS: input.SCS?.toString() ?? null,
174
+ SSBlockSCS: input.SSBlockSCS?.toString() ?? null,
175
+ GSCN: input.GSCN?.toString() ?? null,
176
+ SSREF: input.SSREF?.toString() ?? null,
177
+ SSBlockPattern: input.SSBlockPattern?.toString() ?? null,
178
+ N: input.N?.toString() ?? null,
179
+ M: input.M?.toString() ?? null,
180
+ };
181
+ const result = await getResult("/api/arfcn-calculator-5g/compute", apiRequest);
182
+ const apiResult = apiResultSchema.parse(result);
183
+ return {
184
+ content: [
185
+ {
186
+ type: "text",
187
+ text: JSON.stringify(apiResult, null, 2),
188
+ },
189
+ ],
190
+ structuredContent: apiResult,
191
+ };
192
+ }
193
+ catch {
194
+ return mcpExResponse;
195
+ }
196
+ });
197
+ };
198
+ export default {
199
+ registerComputeTool,
200
+ };
@@ -1,207 +1,200 @@
1
1
  import * as z from "zod/v4";
2
- import { safeApiPost } from "../utils/request.js";
3
2
  import { mcpExResponse } from "../utils/response.js";
4
- export default class ArfcnCalculatorNTN {
5
- mcpServer;
6
- constructor(mcpServer) {
7
- this.mcpServer = mcpServer;
8
- }
9
- registerAllTools = () => {
10
- this.registerComputeTool();
11
- };
12
- registerComputeTool = () => {
13
- const ModeEnum = z.enum(["n", "f"]);
14
- const DirectionEnum = z.enum(["uplink", "downlink"]);
15
- const DuplexModeEnum = z.enum(["TDD", "FDD"]);
16
- const computeInputSchema = z.object({
17
- Mode: ModeEnum.nullable().optional().describe("计算模式,例如 n 表示频点模式,f 表示频率模式"),
18
- DataTransmissionDirection: DirectionEnum.describe("数据传输方向,可选上行(uplink)、下行(downlink)"),
19
- NREF: z.number().int().nullable().optional().describe('频点参考值(NREF),例如 `"504999"`。用于在频点模式(Mode=`"n"`)下确定中心频率。'),
20
- FREF: z.number().nullable().optional().describe('频率参考值(FREF),例如 `"3500.0"`。用于在频率模式(Mode=`"f"`)下直接指定中心频率。'),
21
- Band: z.string().nullable().optional().describe('频段标识符,例如 `"n78"`、`"n41"` 等。用于确定频段的上下行配置、信道栅格(raster)及边界频率。'),
22
- FRaster: z.number().int().nullable().optional().describe("频率栅格(Frequency Raster),单位为 kHz,例如 5、15。用于频点与频率之间的转换计算。"),
23
- SCS: z.number().int().nullable().optional().describe("子载波间隔(Subcarrier Spacing),单位为 kHz,例如 15、30。影响资源块结构和带宽计算。"),
24
- Bandwidth: z
25
- .number()
26
- .nullable()
27
- .optional()
28
- .describe("信道带宽(Channel Bandwidth),单位为 MHz,例如 5、20、100。用于确定传输带宽配置(Transmission Bandwidth Configuration)。"),
29
- SSBlockSCS: z.number().int().nullable().optional().describe("SSB(Synchronization Signal Block)的子载波间隔,单位为 kHz,例如 15、30。"),
30
- SSBlockPattern: z
31
- .string()
32
- .nullable()
33
- .optional()
34
- .describe('SSB 波束扫描图案类型,例如 `"Case A"`、`"Case B"`、`"Case C"`(FR1)或 `"Case D"`、`"Case E"`(FR2),影响 SSB 时域位置和数量。'),
35
- GSCN: z
36
- .number()
37
- .int()
38
- .nullable()
39
- .optional()
40
- .describe("全局同步信道号(Global Synchronization Channel Number),用于粗粒度频率搜索,特别是在非服务小区初始接入时。例如 504990"),
41
- SSREF: z.number().nullable().optional().describe("SSB 中心频率对应的参考频率(单位:Hz 或 MHz,依上下文而定),常用于从 GSCN 或 SSB 配置反推绝对频率。"),
42
- N: z.number().int().nullable().optional().describe("用于 SSB 频域位置计算的参数 N,通常与 GSCN 或 raster 相关。例如 6312"),
43
- M: z.number().int().nullable().optional().describe("SSB 频域偏移步长因子,取决于频段和 SSB 子载波间隔。例如 1、3、5"),
44
- });
45
- const computeOutputSchema = z.object({
46
- Mode: ModeEnum.nullable().optional(),
47
- Mode_Error: z.string().nullable().optional(),
48
- DataTransmissionDirection: DirectionEnum.nullable().optional(),
49
- DataTransmissionDirection_Error: z.string().nullable().optional(),
50
- NREF: z.number().int().nullable().optional(),
51
- NREF_Error: z.string().nullable().optional(),
52
- FREF: z.number().nullable().optional(),
53
- FREF_Error: z.string().nullable().optional(),
54
- FGlobalRaster: z.number().nullable().optional(), // 全局频率栅格,kHz(数值)
55
- FrequencyRangeDesignation: z.string().nullable().optional(), // 频率范围标识符
56
- BandOptions: z.array(z.string()).nullable().optional(),
57
- BandOptions_Error: z.string().nullable().optional(),
58
- Band: z.string().nullable().optional(),
59
- Band_Error: z.string().nullable().optional(),
60
- FREF_Low: z.number().nullable().optional(),
61
- FREF_High: z.number().nullable().optional(),
62
- FRasterOptions_Error: z.string().nullable().optional(),
63
- FRasterOptions: z.array(z.string()).nullable().optional(),
64
- FRaster: z.number().nullable().optional(),
65
- FRaster_Error: z.string().nullable().optional(),
66
- NREF_StepSize: z.number().int().nullable().optional(),
67
- NREF_First: z.number().int().nullable().optional(),
68
- NREF_Last: z.number().int().nullable().optional(),
69
- DuplexMode: DuplexModeEnum.nullable().optional(),
70
- SCSOptions: z.array(z.string()).nullable().optional(),
71
- SCSOptions_Error: z.string().nullable().optional(),
72
- SCS: z.string().nullable().optional(),
73
- SCS_Error: z.string().nullable().optional(),
74
- BandwidthOptions: z.array(z.string()).nullable().optional(),
75
- BandwidthOptions_Error: z.string().nullable().optional(),
76
- Bandwidth: z.number().nullable().optional(), // 带宽单位可能是 MHz,但以数字形式
77
- Bandwidth_Error: z.string().nullable().optional(),
78
- NRB: z.number().int().nullable().optional(), // 资源块数量,整数
79
- MinimumGuardband: z.number().nullable().optional(), // 最小保护带宽,kHz(数值)
80
- FREF_AvailableLow: z.number().nullable().optional(),
81
- FREF_AvailableHigh: z.number().nullable().optional(),
82
- SSBlockSCSOptions: z.array(z.number()).nullable().optional(),
83
- SSBlockSCSOptions_Error: z.string().nullable().optional(),
84
- SSBlockSCS: z.number().nullable().optional(),
85
- SSBlockSCS_Error: z.string().nullable().optional(),
86
- SSBlockPatternOptions: z.array(z.string()).nullable().optional(),
87
- SSBlockPatternOptions_Error: z.string().nullable().optional(),
88
- SSBlockPattern: z.string().nullable().optional(),
89
- SSBlockPattern_Error: z.string().nullable().optional(),
90
- NRaster: z.number().nullable().optional(),
91
- GSCN_First: z.number().int().nullable().optional(),
92
- GSCN_Last: z.number().int().nullable().optional(),
93
- GSCN_StepSize: z.number().int().nullable().optional(),
94
- GSCN: z.number().int().nullable().optional(),
95
- GSCN_Error: z.string().nullable().optional(),
96
- SSREF: z.number().nullable().optional(),
97
- SSREF_Error: z.string().nullable().optional(),
98
- SSBlockNREF: z.number().int().nullable().optional(),
99
- N: z.number().int().nullable().optional(),
100
- N_Error: z.string().nullable().optional(),
101
- MOptions: z.array(z.number()).nullable().optional(),
102
- MOptions_Error: z.string().nullable().optional(),
103
- M: z.number().int().nullable().optional(),
104
- M_Error: z.string().nullable().optional(),
105
- });
106
- const apiResultSchema = z.object({
107
- Mode: ModeEnum.nullable().optional(),
108
- Mode_Error: z.string().nullable().optional(),
109
- DataTransmissionDirection: DirectionEnum.nullable().optional(),
110
- DataTransmissionDirection_Error: z.string().nullable().optional(),
111
- NREF: z.string().nullable().optional(),
112
- NREF_Error: z.string().nullable().optional(),
113
- FREF: z.string().nullable().optional(),
114
- FREF_Error: z.string().nullable().optional(),
115
- FGlobalRaster: z.string().nullable().optional(), // 全局频率栅格,kHz
116
- FrequencyRangeDesignation: z.string().nullable().optional(), // 频率范围标识符
117
- BandOptions: z.array(z.string()).nullable().optional(),
118
- BandOptions_Error: z.string().nullable().optional(),
119
- Band: z.string().nullable().optional(),
120
- Band_Error: z.string().nullable().optional(),
121
- FREF_Low: z.string().nullable().optional(),
122
- FREF_High: z.string().nullable().optional(),
123
- FRasterOptions_Error: z.string().nullable().optional(),
124
- FRasterOptions: z.array(z.string()).nullable().optional(),
125
- FRaster: z.string().nullable().optional(),
126
- FRaster_Error: z.string().nullable().optional(),
127
- NREF_StepSize: z.string().nullable().optional(),
128
- NREF_First: z.string().nullable().optional(),
129
- NREF_Last: z.string().nullable().optional(),
130
- DuplexMode: DuplexModeEnum.nullable().optional(),
131
- SCSOptions: z.array(z.string()).nullable().optional(),
132
- SCSOptions_Error: z.string().nullable().optional(),
133
- SCS: z.string().nullable().optional(),
134
- SCS_Error: z.string().nullable().optional(),
135
- BandwidthOptions: z.array(z.string()).nullable().optional(),
136
- BandwidthOptions_Error: z.string().nullable().optional(),
137
- Bandwidth: z.string().nullable().optional(),
138
- Bandwidth_Error: z.string().nullable().optional(),
139
- NRB: z.string().nullable().optional(),
140
- MinimumGuardband: z.string().nullable().optional(),
141
- FREF_AvailableLow: z.string().nullable().optional(),
142
- FREF_AvailableHigh: z.string().nullable().optional(),
143
- SSBlockSCSOptions: z.array(z.string()).nullable().optional(),
144
- SSBlockSCSOptions_Error: z.string().nullable().optional(),
145
- SSBlockSCS: z.string().nullable().optional(),
146
- SSBlockSCS_Error: z.string().nullable().optional(),
147
- SSBlockPatternOptions: z.array(z.string()).nullable().optional(),
148
- SSBlockPatternOptions_Error: z.string().nullable().optional(),
149
- SSBlockPattern: z.string().nullable().optional(),
150
- SSBlockPattern_Error: z.string().nullable().optional(),
151
- NRaster: z.string().nullable().optional(),
152
- GSCN_First: z.string().nullable().optional(),
153
- GSCN_Last: z.string().nullable().optional(),
154
- GSCN_StepSize: z.string().nullable().optional(),
155
- GSCN: z.string().nullable().optional(),
156
- GSCN_Error: z.string().nullable().optional(),
157
- SSREF: z.string().nullable().optional(),
158
- SSREF_Error: z.string().nullable().optional(),
159
- SSBlockNREF: z.string().nullable().optional(),
160
- N: z.string().nullable().optional(),
161
- N_Error: z.string().nullable().optional(),
162
- MOptions: z.array(z.string()).nullable().optional(),
163
- MOptions_Error: z.string().nullable().optional(),
164
- M: z.string().nullable().optional(),
165
- M_Error: z.string().nullable().optional(),
166
- });
167
- this.mcpServer.registerTool("arfcn_calculator_ntn_compute", {
168
- title: "NTN频点频率转换与对应频带信息",
169
- description: "支持NTN网络中频率与频点之间的相互转换,并附带特定频段的详细信息展示",
170
- inputSchema: computeInputSchema,
171
- outputSchema: computeOutputSchema,
172
- }, async (input) => {
173
- try {
174
- const apiRequest = {
175
- Mode: input.Mode ?? (input.NREF && "n"),
176
- DataTransmissionDirection: input.DataTransmissionDirection,
177
- Band: input.Band?.replaceAll("b", "").replaceAll("B", "") ?? null,
178
- NERF: input.NREF?.toString() ?? null,
179
- FERF: input.FREF?.toString() ?? null,
180
- Bandwidth: input.Bandwidth?.toString() ?? null,
181
- FRaster: input.FRaster?.toString() ?? null,
182
- SCS: input.SCS?.toString() ?? null,
183
- SSBlockSCS: input.SSBlockSCS?.toString() ?? null,
184
- GSCN: input.GSCN?.toString() ?? null,
185
- SSREF: input.SSREF?.toString() ?? null,
186
- SSBlockPattern: input.SSBlockPattern?.toString() ?? null,
187
- N: input.N?.toString() ?? null,
188
- M: input.M?.toString() ?? null,
189
- };
190
- const result = await safeApiPost("/api/arfcn-calculator-ntn/compute", apiRequest);
191
- const apiResult = apiResultSchema.parse(result);
192
- return {
193
- content: [
194
- {
195
- type: "text",
196
- text: JSON.stringify(apiResult, null, 2),
197
- },
198
- ],
199
- structuredContent: apiResult,
200
- };
201
- }
202
- catch {
203
- return mcpExResponse;
204
- }
205
- });
206
- };
207
- }
3
+ const registerComputeTool = (mcpServer, getResult) => {
4
+ const ModeEnum = z.enum(["n", "f"]);
5
+ const DirectionEnum = z.enum(["uplink", "downlink"]);
6
+ const DuplexModeEnum = z.enum(["TDD", "FDD"]);
7
+ const computeInputSchema = z.object({
8
+ Mode: ModeEnum.nullable().optional().describe("计算模式,例如 n 表示频点模式,f 表示频率模式"),
9
+ DataTransmissionDirection: DirectionEnum.describe("数据传输方向,可选上行(uplink)、下行(downlink)"),
10
+ NREF: z.number().int().nullable().optional().describe('频点参考值(NREF),例如 `"504999"`。用于在频点模式(Mode=`"n"`)下确定中心频率。'),
11
+ FREF: z.number().nullable().optional().describe('频率参考值(FREF),例如 `"3500.0"`。用于在频率模式(Mode=`"f"`)下直接指定中心频率。'),
12
+ Band: z.string().nullable().optional().describe('频段标识符,例如 `"n78"`、`"n41"` 等。用于确定频段的上下行配置、信道栅格(raster)及边界频率。'),
13
+ FRaster: z.number().int().nullable().optional().describe("频率栅格(Frequency Raster),单位为 kHz,例如 5、15。用于频点与频率之间的转换计算。"),
14
+ SCS: z.number().int().nullable().optional().describe("子载波间隔(Subcarrier Spacing),单位为 kHz,例如 15、30。影响资源块结构和带宽计算。"),
15
+ Bandwidth: z
16
+ .number()
17
+ .nullable()
18
+ .optional()
19
+ .describe("信道带宽(Channel Bandwidth),单位为 MHz,例如 5、20、100。用于确定传输带宽配置(Transmission Bandwidth Configuration)。"),
20
+ SSBlockSCS: z.number().int().nullable().optional().describe("SSB(Synchronization Signal Block)的子载波间隔,单位为 kHz,例如 15、30。"),
21
+ SSBlockPattern: z
22
+ .string()
23
+ .nullable()
24
+ .optional()
25
+ .describe('SSB 波束扫描图案类型,例如 `"Case A"`、`"Case B"`、`"Case C"`(FR1)或 `"Case D"`、`"Case E"`(FR2),影响 SSB 时域位置和数量。'),
26
+ GSCN: z
27
+ .number()
28
+ .int()
29
+ .nullable()
30
+ .optional()
31
+ .describe("全局同步信道号(Global Synchronization Channel Number),用于粗粒度频率搜索,特别是在非服务小区初始接入时。例如 504990"),
32
+ SSREF: z.number().nullable().optional().describe("SSB 中心频率对应的参考频率(单位:Hz 或 MHz,依上下文而定),常用于从 GSCN 或 SSB 配置反推绝对频率。"),
33
+ N: z.number().int().nullable().optional().describe("用于 SSB 频域位置计算的参数 N,通常与 GSCN raster 相关。例如 6312"),
34
+ M: z.number().int().nullable().optional().describe("SSB 频域偏移步长因子,取决于频段和 SSB 子载波间隔。例如 1、3、5"),
35
+ });
36
+ const computeOutputSchema = z.object({
37
+ Mode: ModeEnum.nullable().optional(),
38
+ Mode_Error: z.string().nullable().optional(),
39
+ DataTransmissionDirection: DirectionEnum.nullable().optional(),
40
+ DataTransmissionDirection_Error: z.string().nullable().optional(),
41
+ NREF: z.number().int().nullable().optional(),
42
+ NREF_Error: z.string().nullable().optional(),
43
+ FREF: z.number().nullable().optional(),
44
+ FREF_Error: z.string().nullable().optional(),
45
+ FGlobalRaster: z.number().nullable().optional(), // 全局频率栅格,kHz(数值)
46
+ FrequencyRangeDesignation: z.string().nullable().optional(), // 频率范围标识符
47
+ BandOptions: z.array(z.string()).nullable().optional(),
48
+ BandOptions_Error: z.string().nullable().optional(),
49
+ Band: z.string().nullable().optional(),
50
+ Band_Error: z.string().nullable().optional(),
51
+ FREF_Low: z.number().nullable().optional(),
52
+ FREF_High: z.number().nullable().optional(),
53
+ FRasterOptions_Error: z.string().nullable().optional(),
54
+ FRasterOptions: z.array(z.string()).nullable().optional(),
55
+ FRaster: z.number().nullable().optional(),
56
+ FRaster_Error: z.string().nullable().optional(),
57
+ NREF_StepSize: z.number().int().nullable().optional(),
58
+ NREF_First: z.number().int().nullable().optional(),
59
+ NREF_Last: z.number().int().nullable().optional(),
60
+ DuplexMode: DuplexModeEnum.nullable().optional(),
61
+ SCSOptions: z.array(z.string()).nullable().optional(),
62
+ SCSOptions_Error: z.string().nullable().optional(),
63
+ SCS: z.string().nullable().optional(),
64
+ SCS_Error: z.string().nullable().optional(),
65
+ BandwidthOptions: z.array(z.string()).nullable().optional(),
66
+ BandwidthOptions_Error: z.string().nullable().optional(),
67
+ Bandwidth: z.number().nullable().optional(), // 带宽单位可能是 MHz,但以数字形式
68
+ Bandwidth_Error: z.string().nullable().optional(),
69
+ NRB: z.number().int().nullable().optional(), // 资源块数量,整数
70
+ MinimumGuardband: z.number().nullable().optional(), // 最小保护带宽,kHz(数值)
71
+ FREF_AvailableLow: z.number().nullable().optional(),
72
+ FREF_AvailableHigh: z.number().nullable().optional(),
73
+ SSBlockSCSOptions: z.array(z.number()).nullable().optional(),
74
+ SSBlockSCSOptions_Error: z.string().nullable().optional(),
75
+ SSBlockSCS: z.number().nullable().optional(),
76
+ SSBlockSCS_Error: z.string().nullable().optional(),
77
+ SSBlockPatternOptions: z.array(z.string()).nullable().optional(),
78
+ SSBlockPatternOptions_Error: z.string().nullable().optional(),
79
+ SSBlockPattern: z.string().nullable().optional(),
80
+ SSBlockPattern_Error: z.string().nullable().optional(),
81
+ NRaster: z.number().nullable().optional(),
82
+ GSCN_First: z.number().int().nullable().optional(),
83
+ GSCN_Last: z.number().int().nullable().optional(),
84
+ GSCN_StepSize: z.number().int().nullable().optional(),
85
+ GSCN: z.number().int().nullable().optional(),
86
+ GSCN_Error: z.string().nullable().optional(),
87
+ SSREF: z.number().nullable().optional(),
88
+ SSREF_Error: z.string().nullable().optional(),
89
+ SSBlockNREF: z.number().int().nullable().optional(),
90
+ N: z.number().int().nullable().optional(),
91
+ N_Error: z.string().nullable().optional(),
92
+ MOptions: z.array(z.number()).nullable().optional(),
93
+ MOptions_Error: z.string().nullable().optional(),
94
+ M: z.number().int().nullable().optional(),
95
+ M_Error: z.string().nullable().optional(),
96
+ });
97
+ const apiResultSchema = z.object({
98
+ Mode: ModeEnum.nullable().optional(),
99
+ Mode_Error: z.string().nullable().optional(),
100
+ DataTransmissionDirection: DirectionEnum.nullable().optional(),
101
+ DataTransmissionDirection_Error: z.string().nullable().optional(),
102
+ NREF: z.string().nullable().optional(),
103
+ NREF_Error: z.string().nullable().optional(),
104
+ FREF: z.string().nullable().optional(),
105
+ FREF_Error: z.string().nullable().optional(),
106
+ FGlobalRaster: z.string().nullable().optional(), // 全局频率栅格,kHz
107
+ FrequencyRangeDesignation: z.string().nullable().optional(), // 频率范围标识符
108
+ BandOptions: z.array(z.string()).nullable().optional(),
109
+ BandOptions_Error: z.string().nullable().optional(),
110
+ Band: z.string().nullable().optional(),
111
+ Band_Error: z.string().nullable().optional(),
112
+ FREF_Low: z.string().nullable().optional(),
113
+ FREF_High: z.string().nullable().optional(),
114
+ FRasterOptions_Error: z.string().nullable().optional(),
115
+ FRasterOptions: z.array(z.string()).nullable().optional(),
116
+ FRaster: z.string().nullable().optional(),
117
+ FRaster_Error: z.string().nullable().optional(),
118
+ NREF_StepSize: z.string().nullable().optional(),
119
+ NREF_First: z.string().nullable().optional(),
120
+ NREF_Last: z.string().nullable().optional(),
121
+ DuplexMode: DuplexModeEnum.nullable().optional(),
122
+ SCSOptions: z.array(z.string()).nullable().optional(),
123
+ SCSOptions_Error: z.string().nullable().optional(),
124
+ SCS: z.string().nullable().optional(),
125
+ SCS_Error: z.string().nullable().optional(),
126
+ BandwidthOptions: z.array(z.string()).nullable().optional(),
127
+ BandwidthOptions_Error: z.string().nullable().optional(),
128
+ Bandwidth: z.string().nullable().optional(),
129
+ Bandwidth_Error: z.string().nullable().optional(),
130
+ NRB: z.string().nullable().optional(),
131
+ MinimumGuardband: z.string().nullable().optional(),
132
+ FREF_AvailableLow: z.string().nullable().optional(),
133
+ FREF_AvailableHigh: z.string().nullable().optional(),
134
+ SSBlockSCSOptions: z.array(z.string()).nullable().optional(),
135
+ SSBlockSCSOptions_Error: z.string().nullable().optional(),
136
+ SSBlockSCS: z.string().nullable().optional(),
137
+ SSBlockSCS_Error: z.string().nullable().optional(),
138
+ SSBlockPatternOptions: z.array(z.string()).nullable().optional(),
139
+ SSBlockPatternOptions_Error: z.string().nullable().optional(),
140
+ SSBlockPattern: z.string().nullable().optional(),
141
+ SSBlockPattern_Error: z.string().nullable().optional(),
142
+ NRaster: z.string().nullable().optional(),
143
+ GSCN_First: z.string().nullable().optional(),
144
+ GSCN_Last: z.string().nullable().optional(),
145
+ GSCN_StepSize: z.string().nullable().optional(),
146
+ GSCN: z.string().nullable().optional(),
147
+ GSCN_Error: z.string().nullable().optional(),
148
+ SSREF: z.string().nullable().optional(),
149
+ SSREF_Error: z.string().nullable().optional(),
150
+ SSBlockNREF: z.string().nullable().optional(),
151
+ N: z.string().nullable().optional(),
152
+ N_Error: z.string().nullable().optional(),
153
+ MOptions: z.array(z.string()).nullable().optional(),
154
+ MOptions_Error: z.string().nullable().optional(),
155
+ M: z.string().nullable().optional(),
156
+ M_Error: z.string().nullable().optional(),
157
+ });
158
+ mcpServer.registerTool("arfcn_calculator_ntn_compute", {
159
+ title: "NTN频点频率转换与对应频带信息",
160
+ description: "支持NTN网络中频率与频点之间的相互转换,并附带特定频段的详细信息展示",
161
+ inputSchema: computeInputSchema,
162
+ outputSchema: computeOutputSchema,
163
+ }, async (input) => {
164
+ try {
165
+ const apiRequest = {
166
+ Mode: input.Mode ?? (input.NREF && "n"),
167
+ DataTransmissionDirection: input.DataTransmissionDirection,
168
+ Band: input.Band?.replaceAll("b", "").replaceAll("B", "") ?? null,
169
+ NERF: input.NREF?.toString() ?? null,
170
+ FERF: input.FREF?.toString() ?? null,
171
+ Bandwidth: input.Bandwidth?.toString() ?? null,
172
+ FRaster: input.FRaster?.toString() ?? null,
173
+ SCS: input.SCS?.toString() ?? null,
174
+ SSBlockSCS: input.SSBlockSCS?.toString() ?? null,
175
+ GSCN: input.GSCN?.toString() ?? null,
176
+ SSREF: input.SSREF?.toString() ?? null,
177
+ SSBlockPattern: input.SSBlockPattern?.toString() ?? null,
178
+ N: input.N?.toString() ?? null,
179
+ M: input.M?.toString() ?? null,
180
+ };
181
+ const result = await getResult("/api/arfcn-calculator-ntn/compute", apiRequest);
182
+ const apiResult = apiResultSchema.parse(result);
183
+ return {
184
+ content: [
185
+ {
186
+ type: "text",
187
+ text: JSON.stringify(apiResult, null, 2),
188
+ },
189
+ ],
190
+ structuredContent: apiResult,
191
+ };
192
+ }
193
+ catch {
194
+ return mcpExResponse;
195
+ }
196
+ });
197
+ };
198
+ export default {
199
+ registerComputeTool,
200
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rfhub-mcp",
3
- "version": "0.7.0",
3
+ "version": "0.8.0",
4
4
  "title": "RFHub MCP Server",
5
5
  "description": "RFHub MCP Server",
6
6
  "websiteUrl": "https://rfhub.cn/mcp-server",