calc-mcp-server 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (110) hide show
  1. package/.claude/commands/opsx/apply.md +152 -0
  2. package/.claude/commands/opsx/archive.md +157 -0
  3. package/.claude/commands/opsx/bulk-archive.md +242 -0
  4. package/.claude/commands/opsx/continue.md +114 -0
  5. package/.claude/commands/opsx/explore.md +174 -0
  6. package/.claude/commands/opsx/ff.md +94 -0
  7. package/.claude/commands/opsx/new.md +69 -0
  8. package/.claude/commands/opsx/onboard.md +534 -0
  9. package/.claude/commands/opsx/sync.md +134 -0
  10. package/.claude/commands/opsx/verify.md +164 -0
  11. package/.claude/settings.local.json +8 -0
  12. package/.claude/skills/npm-publish/SKILL.md +164 -0
  13. package/.claude/skills/openspec-apply-change/SKILL.md +156 -0
  14. package/.claude/skills/openspec-archive-change/SKILL.md +161 -0
  15. package/.claude/skills/openspec-bulk-archive-change/SKILL.md +246 -0
  16. package/.claude/skills/openspec-continue-change/SKILL.md +118 -0
  17. package/.claude/skills/openspec-explore/SKILL.md +289 -0
  18. package/.claude/skills/openspec-ff-change/SKILL.md +101 -0
  19. package/.claude/skills/openspec-new-change/SKILL.md +74 -0
  20. package/.claude/skills/openspec-onboard/SKILL.md +538 -0
  21. package/.claude/skills/openspec-sync-specs/SKILL.md +138 -0
  22. package/.claude/skills/openspec-verify-change/SKILL.md +168 -0
  23. package/CLAUDE.md +92 -0
  24. package/README.md +319 -0
  25. package/build/engines/decimal.d.ts +10 -0
  26. package/build/engines/decimal.d.ts.map +1 -0
  27. package/build/engines/decimal.js +61 -0
  28. package/build/engines/decimal.js.map +1 -0
  29. package/build/engines/programmer.d.ts +18 -0
  30. package/build/engines/programmer.d.ts.map +1 -0
  31. package/build/engines/programmer.js +103 -0
  32. package/build/engines/programmer.js.map +1 -0
  33. package/build/errors/handler.d.ts +10 -0
  34. package/build/errors/handler.d.ts.map +1 -0
  35. package/build/errors/handler.js +37 -0
  36. package/build/errors/handler.js.map +1 -0
  37. package/build/errors/types.d.ts +25 -0
  38. package/build/errors/types.d.ts.map +1 -0
  39. package/build/errors/types.js +2 -0
  40. package/build/errors/types.js.map +1 -0
  41. package/build/index.d.ts +3 -0
  42. package/build/index.d.ts.map +1 -0
  43. package/build/index.js +16 -0
  44. package/build/index.js.map +1 -0
  45. package/build/mcp/server.d.ts +3 -0
  46. package/build/mcp/server.d.ts.map +1 -0
  47. package/build/mcp/server.js +270 -0
  48. package/build/mcp/server.js.map +1 -0
  49. package/build/mcp/tools/ascii.d.ts +11 -0
  50. package/build/mcp/tools/ascii.d.ts.map +1 -0
  51. package/build/mcp/tools/ascii.js +93 -0
  52. package/build/mcp/tools/ascii.js.map +1 -0
  53. package/build/mcp/tools/basic.d.ts +6 -0
  54. package/build/mcp/tools/basic.d.ts.map +1 -0
  55. package/build/mcp/tools/basic.js +34 -0
  56. package/build/mcp/tools/basic.js.map +1 -0
  57. package/build/mcp/tools/conversion.d.ts +8 -0
  58. package/build/mcp/tools/conversion.d.ts.map +1 -0
  59. package/build/mcp/tools/conversion.js +81 -0
  60. package/build/mcp/tools/conversion.js.map +1 -0
  61. package/build/mcp/tools/programmer.d.ts +6 -0
  62. package/build/mcp/tools/programmer.d.ts.map +1 -0
  63. package/build/mcp/tools/programmer.js +29 -0
  64. package/build/mcp/tools/programmer.js.map +1 -0
  65. package/build/parser/ast.d.ts +47 -0
  66. package/build/parser/ast.d.ts.map +1 -0
  67. package/build/parser/ast.js +2 -0
  68. package/build/parser/ast.js.map +1 -0
  69. package/build/parser/lexer.d.ts +24 -0
  70. package/build/parser/lexer.d.ts.map +1 -0
  71. package/build/parser/lexer.js +168 -0
  72. package/build/parser/lexer.js.map +1 -0
  73. package/build/parser/parser.d.ts +14 -0
  74. package/build/parser/parser.d.ts.map +1 -0
  75. package/build/parser/parser.js +115 -0
  76. package/build/parser/parser.js.map +1 -0
  77. package/docs/plans/2025-02-24-mcp-calculator-design.md +344 -0
  78. package/docs/plans/2025-02-24-mcp-calculator-implementation.md +2626 -0
  79. package/openspec/changes/archive/2026-02-24-simplify-ascii-tools/.openspec.yaml +2 -0
  80. package/openspec/changes/archive/2026-02-24-simplify-ascii-tools/design.md +46 -0
  81. package/openspec/changes/archive/2026-02-24-simplify-ascii-tools/proposal.md +21 -0
  82. package/openspec/changes/archive/2026-02-24-simplify-ascii-tools/specs/ascii-conversion/spec.md +22 -0
  83. package/openspec/changes/archive/2026-02-24-simplify-ascii-tools/tasks.md +24 -0
  84. package/openspec/config.yaml +20 -0
  85. package/openspec/specs/ascii-conversion/spec.md +43 -0
  86. package/package.json +40 -0
  87. package/src/engines/decimal.ts +69 -0
  88. package/src/engines/programmer.ts +112 -0
  89. package/src/errors/handler.ts +55 -0
  90. package/src/errors/types.ts +37 -0
  91. package/src/index.ts +20 -0
  92. package/src/mcp/server.ts +287 -0
  93. package/src/mcp/tools/ascii.ts +116 -0
  94. package/src/mcp/tools/basic.ts +44 -0
  95. package/src/mcp/tools/conversion.ts +95 -0
  96. package/src/mcp/tools/programmer.ts +36 -0
  97. package/src/parser/ast.ts +51 -0
  98. package/src/parser/lexer.ts +216 -0
  99. package/src/parser/parser.ts +154 -0
  100. package/test/integration/ascii.test.ts +450 -0
  101. package/test/integration/basic-calculate.test.ts +272 -0
  102. package/test/integration/conversion.test.ts +357 -0
  103. package/test/integration/programmer-calculate.test.ts +363 -0
  104. package/test/unit/decimal-engine.test.ts +134 -0
  105. package/test/unit/error-handler.test.ts +173 -0
  106. package/test/unit/lexer.test.ts +176 -0
  107. package/test/unit/parser.test.ts +197 -0
  108. package/test/unit/programmer-engine.test.ts +234 -0
  109. package/tsconfig.json +20 -0
  110. package/vitest.config.ts +13 -0
package/README.md ADDED
@@ -0,0 +1,319 @@
1
+ # MCP Calculator
2
+
3
+ 一个功能强大的 MCP (Model Context Protocol) Server 计算器,提供基础算术运算和程序员计算功能。
4
+
5
+ ## 项目简介
6
+
7
+ MCP Calculator 是一个使用 TypeScript 实现的计算器服务器,通过 MCP 协议提供各种计算功能。它支持高精度十进制运算和程序员级整数运算(包括位运算),以及进制转换和 ASCII 字符转换。
8
+
9
+ ## 功能特性
10
+
11
+ ### 基础计算器 (`basic_calculate`)
12
+ - 支持四则运算:加 (+)、减 (-)、乘 (*)、除 (/)、取余 (%)
13
+ - 支持括号优先级
14
+ - 使用 Decimal.js 实现高精度计算
15
+ - 自动处理浮点数精度问题(如 0.1 + 0.2 = 0.3)
16
+
17
+ ### 程序员计算器 (`programmer_calculate`)
18
+ - 整数算术运算
19
+ - 位运算:按位与 (&)、按位或 (|)、按位异或 (^)、按位取反 (~)
20
+ - 位移运算:左移 (<<)、右移 (>>)、无符号右移 (>>>)
21
+ - 支持多种字面量格式:
22
+ - 十进制:`42`
23
+ - 十六进制:`0xFF`
24
+ - 二进制:`0b1010`
25
+ - 八进制:`0o755`
26
+ - 字符字面量:`'A'` (自动转换为 ASCII 值)
27
+
28
+ ### 进制转换 (`convert_base`)
29
+ - 支持进制:2(二进制)、8(八进制)、10(十进制)、16(十六进制)
30
+ - 双向转换,任意进制互转
31
+
32
+ ### ASCII 转换 (`ascii_to_number`, `number_to_ascii`, `multiple_ascii_to_number`)
33
+ - ASCII 字符转数值
34
+ - 数值转 ASCII 字符
35
+ - 批量 ASCII 字符串转数值数组
36
+
37
+ ## 安装方法
38
+
39
+ ```bash
40
+ # 克隆仓库
41
+ git clone <repository-url>
42
+ cd calculator
43
+
44
+ # 安装依赖
45
+ npm install
46
+
47
+ # 构建项目
48
+ npm run build
49
+ ```
50
+
51
+ ## 使用方法
52
+
53
+ ### 作为 MCP Server 配置
54
+
55
+ 在 MCP 客户端配置文件中添加:
56
+
57
+ ```json
58
+ {
59
+ "mcpServers": {
60
+ "calculator": {
61
+ "command": "node",
62
+ "args": ["/path/to/calculator/dist/index.js"]
63
+ }
64
+ }
65
+ }
66
+ ```
67
+
68
+ ### 直接运行
69
+
70
+ ```bash
71
+ # 开发模式(监听文件变化)
72
+ npm run dev
73
+
74
+ # 构建生产版本
75
+ npm run build
76
+ ```
77
+
78
+ ## 可用工具列表
79
+
80
+ ### 1. basic_calculate
81
+ 基础算术表达式计算
82
+
83
+ **参数:**
84
+ - `expression` (string): 要计算的算术表达式
85
+
86
+ **示例:**
87
+ ```
88
+ basic_calculate("2 + 3 * 4") // 返回: "14"
89
+ basic_calculate("(10 - 4) / 2") // 返回: "3"
90
+ basic_calculate("0.1 + 0.2") // 返回: "0.3"
91
+ basic_calculate("15 % 4") // 返回: "3"
92
+ ```
93
+
94
+ ### 2. programmer_calculate
95
+ 程序员计算器表达式计算
96
+
97
+ **参数:**
98
+ - `expression` (string): 要计算的程序员表达式
99
+
100
+ **示例:**
101
+ ```
102
+ programmer_calculate("0xA + 0x5") // 返回: "15" (十进制)
103
+ programmer_calculate("0b1010 & 0b1100") // 返回: "8"
104
+ programmer_calculate("'A' + 1") // 返回: "66" (ASCII 'B')
105
+ programmer_calculate("255 << 2") // 返回: "1020"
106
+ programmer_calculate("~0") // 返回: "-1"
107
+ ```
108
+
109
+ ### 3. convert_base
110
+ 数字进制转换
111
+
112
+ **参数:**
113
+ - `value` (string): 要转换的数值
114
+ - `from` (number): 源进制 (2, 8, 10, 16)
115
+ - `to` (number): 目标进制 (2, 8, 10, 16)
116
+
117
+ **示例:**
118
+ ```
119
+ convert_base("1010", 2, 10) // 返回: { value: "10", representation: "0b1010 = 10" }
120
+ convert_base("FF", 16, 2) // 返回: { value: "11111111", representation: "0xFF = 0b11111111" }
121
+ convert_base("10", 10, 16) // 返回: { value: "A", representation: "10 = 0xA" }
122
+ ```
123
+
124
+ ### 4. ascii_to_number
125
+ ASCII 字符转数值
126
+
127
+ **参数:**
128
+ - `char` (string): 单个 ASCII 字符
129
+
130
+ **示例:**
131
+ ```
132
+ ascii_to_number("A") // 返回: { char: "A", value: 65, binary: "0b1000001", hex: "0x41" }
133
+ ```
134
+
135
+ ### 5. number_to_ascii
136
+ 数值转 ASCII 字符
137
+
138
+ **参数:**
139
+ - `number` (number): 数值 (0-255)
140
+
141
+ **示例:**
142
+ ```
143
+ number_to_ascii(65) // 返回: { number: 65, char: "A", description: "Letter A" }
144
+ ```
145
+
146
+ ### 6. multiple_ascii_to_number
147
+ 批量 ASCII 字符串转数值数组
148
+
149
+ **参数:**
150
+ - `text` (string): ASCII 字符串
151
+
152
+ **示例:**
153
+ ```
154
+ multiple_ascii_to_number("ABC") // 返回: { text: "ABC", values: [65, 66, 67] }
155
+ ```
156
+
157
+ ## 开发指南
158
+
159
+ ### 项目结构
160
+
161
+ ```
162
+ calculator/
163
+ ├── src/
164
+ │ ├── index.ts # MCP Server 入口
165
+ │ ├── mcp/
166
+ │ │ ├── server.ts # MCP Server 实现
167
+ │ │ └── tools/ # MCP 工具实现
168
+ │ │ ├── basic.ts # 基础计算工具
169
+ │ │ ├── programmer.ts # 程序员计算工具
170
+ │ │ ├── conversion.ts # 进制转换工具
171
+ │ │ └── ascii.ts # ASCII 转换工具
172
+ │ ├── engines/
173
+ │ │ ├── decimal.ts # 高精度十进制引擎
174
+ │ │ └── programmer.ts # 程序员计算引擎
175
+ │ ├── parser/
176
+ │ │ ├── lexer.ts # 词法分析器
177
+ │ │ ├── parser.ts # 语法分析器
178
+ │ │ └── ast.ts # 抽象语法树定义
179
+ │ └── errors/
180
+ │ ├── types.ts # 错误类型定义
181
+ │ └── handler.ts # 错误处理器
182
+ ├── test/
183
+ │ ├── unit/ # 单元测试
184
+ │ └── integration/ # 集成测试
185
+ └── dist/ # 编译输出
186
+ ```
187
+
188
+ ### 可用命令
189
+
190
+ ```bash
191
+ # 构建项目
192
+ npm run build
193
+
194
+ # 开发模式(监听文件变化)
195
+ npm run dev
196
+
197
+ # 运行测试
198
+ npm run test
199
+
200
+ # 运行测试(带 UI)
201
+ npm run test:ui
202
+
203
+ # 运行测试覆盖率
204
+ npm run test:coverage
205
+
206
+ # 类型检查
207
+ npm run typecheck
208
+
209
+ # 代码检查
210
+ npm run lint
211
+ ```
212
+
213
+ ### 添加新工具
214
+
215
+ 1. 在 `src/mcp/tools/` 创建新的工具文件
216
+ 2. 实现工具函数,遵循现有工具的模式
217
+ 3. 在 `src/mcp/server.ts` 中注册新工具
218
+ 4. 添加相应的测试
219
+
220
+ ## 返回格式说明
221
+
222
+ 所有工具的返回值均为 JSON 格式:
223
+
224
+ ### 成功响应
225
+ ```json
226
+ {
227
+ "content": [
228
+ {
229
+ "type": "text",
230
+ "text": "计算结果或错误信息"
231
+ }
232
+ ]
233
+ }
234
+ ```
235
+
236
+ ### basic_calculate 返回格式
237
+ ```json
238
+ {
239
+ "result": "计算结果字符串",
240
+ "expression": "原始表达式"
241
+ }
242
+ ```
243
+
244
+ ### programmer_calculate 返回格式
245
+ ```json
246
+ {
247
+ "result": "计算结果字符串",
248
+ "decimal": "十进制表示",
249
+ "hex": "十六进制表示",
250
+ "binary": "二进制表示"
251
+ }
252
+ ```
253
+
254
+ ### convert_base 返回格式
255
+ ```json
256
+ {
257
+ "value": "转换后的值",
258
+ "representation": "完整表示"
259
+ }
260
+ ```
261
+
262
+ ### ASCII 工具返回格式
263
+ ```json
264
+ {
265
+ "char": "字符",
266
+ "value": 数值,
267
+ "binary": "二进制表示",
268
+ "hex": "十六进制表示"
269
+ }
270
+ ```
271
+
272
+ ## 测试覆盖
273
+
274
+ 项目包含全面的单元测试和集成测试:
275
+
276
+ - **测试文件**: 9 个
277
+ - **测试用例**: 229 个
278
+ - **代码覆盖率**: 70.09% 语句覆盖
279
+ - **分支覆盖**: 88.66%
280
+
281
+ 运行测试:
282
+ ```bash
283
+ npm run test:coverage
284
+ ```
285
+
286
+ ## 依赖项
287
+
288
+ ### 运行时依赖
289
+ - `@modelcontextprotocol/sdk`: ^1.0.4 - MCP SDK
290
+ - `decimal.js`: ^10.4.3 - 高精度十进制运算库
291
+
292
+ ### 开发依赖
293
+ - `typescript`: ^5.3.3 - TypeScript 编译器
294
+ - `vitest`: ^1.2.0 - 测试框架
295
+ - `@vitest/coverage-v8`: ^1.2.0 - 代码覆盖率工具
296
+ - `@types/node`: ^20.11.0 - Node.js 类型定义
297
+ - `eslint`: ^8.56.0 - 代码检查工具
298
+
299
+ ## 错误处理
300
+
301
+ 计算器实现了完善的错误处理机制:
302
+
303
+ - **除零错误**: 清晰提示除数为零
304
+ - **语法错误**: 指出表达式中的语法问题位置
305
+ - **无效字符**: 识别并报告表达式中的非法字符
306
+ - **无效进制**: 验证进制转换的参数有效性
307
+ - **数值溢出**: 检测整数运算溢出
308
+
309
+ ## 许可证
310
+
311
+ MIT License
312
+
313
+ ## 贡献
314
+
315
+ 欢迎提交 Issue 和 Pull Request!
316
+
317
+ ## 作者
318
+
319
+ MCP Calculator Development Team
@@ -0,0 +1,10 @@
1
+ import { Decimal } from 'decimal.js';
2
+ import { ASTNode } from '../parser/ast.js';
3
+ export declare class DecimalEngine {
4
+ evaluate(ast: ASTNode): Decimal;
5
+ private visit;
6
+ private visitLiteral;
7
+ private visitBinaryOp;
8
+ private visitUnaryOp;
9
+ }
10
+ //# sourceMappingURL=decimal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decimal.d.ts","sourceRoot":"","sources":["../../src/engines/decimal.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AACrC,OAAO,EAAE,OAAO,EAAqD,MAAM,kBAAkB,CAAC;AAE9F,qBAAa,aAAa;IAExB,QAAQ,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO;IAI/B,OAAO,CAAC,KAAK;IAeb,OAAO,CAAC,YAAY;IAMpB,OAAO,CAAC,aAAa;IA0BrB,OAAO,CAAC,YAAY;CAYrB"}
@@ -0,0 +1,61 @@
1
+ import { Decimal } from 'decimal.js';
2
+ export class DecimalEngine {
3
+ evaluate(ast) {
4
+ return this.visit(ast);
5
+ }
6
+ visit(node) {
7
+ switch (node.type) {
8
+ case 'Literal':
9
+ return this.visitLiteral(node);
10
+ case 'BinaryOp':
11
+ return this.visitBinaryOp(node);
12
+ case 'UnaryOp':
13
+ return this.visitUnaryOp(node);
14
+ case 'Group':
15
+ return this.visit(node.expression);
16
+ default:
17
+ throw new Error(`Unknown node type: ${node.type}`);
18
+ }
19
+ }
20
+ visitLiteral(node) {
21
+ // Strip prefixes for non-decimal literals
22
+ const value = node.value.replace(/^(0x|0b|0o)/, '');
23
+ return new Decimal(value);
24
+ }
25
+ visitBinaryOp(node) {
26
+ const left = this.visit(node.left);
27
+ const right = this.visit(node.right);
28
+ switch (node.operator) {
29
+ case '+':
30
+ return left.plus(right);
31
+ case '-':
32
+ return left.minus(right);
33
+ case '*':
34
+ return left.times(right);
35
+ case '/':
36
+ if (right.isZero()) {
37
+ throw new Error('DivisionByZero');
38
+ }
39
+ return left.dividedBy(right);
40
+ case '%':
41
+ if (right.isZero()) {
42
+ throw new Error('DivisionByZero');
43
+ }
44
+ return left.modulo(right);
45
+ default:
46
+ throw new Error(`不支持运算符 "${node.operator}",请使用程序员计算器进行此运算。`);
47
+ }
48
+ }
49
+ visitUnaryOp(node) {
50
+ const operand = this.visit(node.operand);
51
+ switch (node.operator) {
52
+ case '-':
53
+ return operand.negated();
54
+ case '+':
55
+ return operand;
56
+ default:
57
+ throw new Error(`Unsupported unary operator for decimal engine: ${node.operator}`);
58
+ }
59
+ }
60
+ }
61
+ //# sourceMappingURL=decimal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decimal.js","sourceRoot":"","sources":["../../src/engines/decimal.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAGrC,MAAM,OAAO,aAAa;IAExB,QAAQ,CAAC,GAAY;QACnB,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACzB,CAAC;IAEO,KAAK,CAAC,IAAa;QACzB,QAAQ,IAAI,CAAC,IAAI,EAAE,CAAC;YAClB,KAAK,SAAS;gBACZ,OAAO,IAAI,CAAC,YAAY,CAAC,IAAmB,CAAC,CAAC;YAChD,KAAK,UAAU;gBACb,OAAO,IAAI,CAAC,aAAa,CAAC,IAAoB,CAAC,CAAC;YAClD,KAAK,SAAS;gBACZ,OAAO,IAAI,CAAC,YAAY,CAAC,IAAmB,CAAC,CAAC;YAChD,KAAK,OAAO;gBACV,OAAO,IAAI,CAAC,KAAK,CAAE,IAAkB,CAAC,UAAU,CAAC,CAAC;YACpD;gBACE,MAAM,IAAI,KAAK,CAAC,sBAAuB,IAAY,CAAC,IAAI,EAAE,CAAC,CAAC;QAChE,CAAC;IACH,CAAC;IAEO,YAAY,CAAC,IAAiB;QACpC,0CAA0C;QAC1C,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC;QACpD,OAAO,IAAI,OAAO,CAAC,KAAK,CAAC,CAAC;IAC5B,CAAC;IAEO,aAAa,CAAC,IAAkB;QACtC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACnC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAErC,QAAQ,IAAI,CAAC,QAAQ,EAAE,CAAC;YACtB,KAAK,GAAG;gBACN,OAAO,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC1B,KAAK,GAAG;gBACN,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YAC3B,KAAK,GAAG;gBACN,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YAC3B,KAAK,GAAG;gBACN,IAAI,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC;oBACnB,MAAM,IAAI,KAAK,CAAC,gBAAgB,CAAC,CAAC;gBACpC,CAAC;gBACD,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;YAC/B,KAAK,GAAG;gBACN,IAAI,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC;oBACnB,MAAM,IAAI,KAAK,CAAC,gBAAgB,CAAC,CAAC;gBACpC,CAAC;gBACD,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAC5B;gBACE,MAAM,IAAI,KAAK,CAAC,WAAW,IAAI,CAAC,QAAQ,mBAAmB,CAAC,CAAC;QACjE,CAAC;IACH,CAAC;IAEO,YAAY,CAAC,IAAiB;QACpC,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAEzC,QAAQ,IAAI,CAAC,QAAQ,EAAE,CAAC;YACtB,KAAK,GAAG;gBACN,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;YAC3B,KAAK,GAAG;gBACN,OAAO,OAAO,CAAC;YACjB;gBACE,MAAM,IAAI,KAAK,CAAC,kDAAkD,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;QACvF,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,18 @@
1
+ import { ASTNode } from '../parser/ast.js';
2
+ export declare class ProgrammerEngine {
3
+ private errorHandler;
4
+ /**
5
+ * Evaluates an AST node and returns the result as a bigint.
6
+ *
7
+ * @param ast - The AST node to evaluate
8
+ * @returns The evaluation result as a bigint
9
+ * @throws {RuntimeError} If division by zero is attempted
10
+ * @throws {RuntimeError} If floating point numbers are used
11
+ */
12
+ evaluate(ast: ASTNode): bigint;
13
+ private visit;
14
+ private visitLiteral;
15
+ private visitBinaryOp;
16
+ private visitUnaryOp;
17
+ }
18
+ //# sourceMappingURL=programmer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"programmer.d.ts","sourceRoot":"","sources":["../../src/engines/programmer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAqD,MAAM,kBAAkB,CAAC;AAG9F,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,YAAY,CAAsB;IAE1C;;;;;;;OAOG;IACH,QAAQ,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM;IAI9B,OAAO,CAAC,KAAK;IAeb,OAAO,CAAC,YAAY;IAyBpB,OAAO,CAAC,aAAa;IAuCrB,OAAO,CAAC,YAAY;CAcrB"}
@@ -0,0 +1,103 @@
1
+ import { ErrorHandler } from '../errors/handler.js';
2
+ export class ProgrammerEngine {
3
+ errorHandler = new ErrorHandler();
4
+ /**
5
+ * Evaluates an AST node and returns the result as a bigint.
6
+ *
7
+ * @param ast - The AST node to evaluate
8
+ * @returns The evaluation result as a bigint
9
+ * @throws {RuntimeError} If division by zero is attempted
10
+ * @throws {RuntimeError} If floating point numbers are used
11
+ */
12
+ evaluate(ast) {
13
+ return this.visit(ast);
14
+ }
15
+ visit(node) {
16
+ switch (node.type) {
17
+ case 'Literal':
18
+ return this.visitLiteral(node);
19
+ case 'BinaryOp':
20
+ return this.visitBinaryOp(node);
21
+ case 'UnaryOp':
22
+ return this.visitUnaryOp(node);
23
+ case 'Group':
24
+ return this.visit(node.expression);
25
+ default:
26
+ throw new Error(`Unknown node type: ${node.type}`);
27
+ }
28
+ }
29
+ visitLiteral(node) {
30
+ const { value, tokenType } = node;
31
+ switch (tokenType) {
32
+ case 'NUMBER':
33
+ // Decimal integer
34
+ if (value.includes('.')) {
35
+ throw this.errorHandler.runtimeError('InvalidNumber', 'Floating point numbers not supported in programmer mode');
36
+ }
37
+ return BigInt(value);
38
+ case 'HEX':
39
+ return BigInt(value);
40
+ case 'BINARY':
41
+ return BigInt(value);
42
+ case 'OCTAL':
43
+ return BigInt(value);
44
+ case 'CHAR_LITERAL':
45
+ // Parse char literal like 'A' or '\n'
46
+ const char = value.substring(1, value.length - 1);
47
+ return BigInt(char.charCodeAt(0));
48
+ default:
49
+ throw new Error(`Unsupported literal type: ${tokenType}`);
50
+ }
51
+ }
52
+ visitBinaryOp(node) {
53
+ const left = this.visit(node.left);
54
+ const right = this.visit(node.right);
55
+ switch (node.operator) {
56
+ case '+':
57
+ return left + right;
58
+ case '-':
59
+ return left - right;
60
+ case '*':
61
+ return left * right;
62
+ case '/':
63
+ if (right === 0n) {
64
+ throw this.errorHandler.runtimeError('DivisionByZero', 'Cannot divide by zero');
65
+ }
66
+ return left / right;
67
+ case '%':
68
+ if (right === 0n) {
69
+ throw this.errorHandler.runtimeError('DivisionByZero', 'Cannot divide by zero');
70
+ }
71
+ return left % right;
72
+ case '&':
73
+ return left & right;
74
+ case '|':
75
+ return left | right;
76
+ case '^':
77
+ return left ^ right;
78
+ case '<<':
79
+ return left << right;
80
+ case '>>':
81
+ return left >> right;
82
+ case '>>>':
83
+ // Unsigned right shift - convert to number, shift, back to bigint
84
+ return BigInt(Number(left) >>> Number(right));
85
+ default:
86
+ throw new Error(`Unsupported operator for programmer engine: ${node.operator}`);
87
+ }
88
+ }
89
+ visitUnaryOp(node) {
90
+ const operand = this.visit(node.operand);
91
+ switch (node.operator) {
92
+ case '~':
93
+ return ~operand;
94
+ case '-':
95
+ return -operand;
96
+ case '+':
97
+ return operand;
98
+ default:
99
+ throw new Error(`Unsupported unary operator for programmer engine: ${node.operator}`);
100
+ }
101
+ }
102
+ }
103
+ //# sourceMappingURL=programmer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"programmer.js","sourceRoot":"","sources":["../../src/engines/programmer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import { ErrorType, Position, ErrorResponse, CalculationResponse, SuccessResponse } from './types.js';
2
+ export type { ErrorType, CalculationResponse, ErrorResponse, SuccessResponse };
3
+ export declare class ErrorHandler {
4
+ private suggestions;
5
+ syntaxError(message: string, start: number, end: number): ErrorResponse;
6
+ runtimeError(type: ErrorType, message: string): ErrorResponse;
7
+ createError(type: ErrorType, message: string, position?: Position): ErrorResponse;
8
+ success(result: string, details?: SuccessResponse['details']): SuccessResponse;
9
+ }
10
+ //# sourceMappingURL=handler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../src/errors/handler.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EACT,QAAQ,EAER,aAAa,EACb,mBAAmB,EACnB,eAAe,EAChB,MAAM,YAAY,CAAC;AAEpB,YAAY,EAAE,SAAS,EAAE,mBAAmB,EAAE,aAAa,EAAE,eAAe,EAAE,CAAC;AAE/E,qBAAa,YAAY;IACvB,OAAO,CAAC,WAAW,CASjB;IAEF,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,aAAa;IAIvE,YAAY,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,GAAG,aAAa;IAI7D,WAAW,CACT,IAAI,EAAE,SAAS,EACf,OAAO,EAAE,MAAM,EACf,QAAQ,CAAC,EAAE,QAAQ,GAClB,aAAa;IAYhB,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,eAAe,CAAC,SAAS,CAAC,GAAG,eAAe;CAO/E"}
@@ -0,0 +1,37 @@
1
+ export class ErrorHandler {
2
+ suggestions = {
3
+ SyntaxError: 'Check your expression syntax. Ensure operators and operands are correctly placed.',
4
+ DivisionByZero: 'Division by zero is not allowed. Check your denominators.',
5
+ InvalidNumber: 'The number format is invalid. Check for typos or unsupported formats.',
6
+ OverflowError: 'The number is too large or too small to process.',
7
+ InvalidBase: 'Invalid base specified. Supported bases are 2, 8, 10, and 16.',
8
+ UnmatchedParen: 'Unmatched parenthesis. Ensure every opening parenthesis has a closing one.',
9
+ InvalidOperator: 'Invalid operator for this operation. Check supported operators.',
10
+ EmptyInput: 'Expression cannot be empty. Please provide a valid expression.',
11
+ };
12
+ syntaxError(message, start, end) {
13
+ return this.createError('SyntaxError', message, { start, end });
14
+ }
15
+ runtimeError(type, message) {
16
+ return this.createError(type, message);
17
+ }
18
+ createError(type, message, position) {
19
+ return {
20
+ success: false,
21
+ error: {
22
+ type,
23
+ message,
24
+ position,
25
+ suggestion: this.suggestions[type],
26
+ },
27
+ };
28
+ }
29
+ success(result, details) {
30
+ return {
31
+ success: true,
32
+ result,
33
+ details,
34
+ };
35
+ }
36
+ }
37
+ //# sourceMappingURL=handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handler.js","sourceRoot":"","sources":["../../src/errors/handler.ts"],"names":[],"mappings":"AAWA,MAAM,OAAO,YAAY;IACf,WAAW,GAA8B;QAC/C,WAAW,EAAE,mFAAmF;QAChG,cAAc,EAAE,2DAA2D;QAC3E,aAAa,EAAE,uEAAuE;QACtF,aAAa,EAAE,kDAAkD;QACjE,WAAW,EAAE,+DAA+D;QAC5E,cAAc,EAAE,4EAA4E;QAC5F,eAAe,EAAE,iEAAiE;QAClF,UAAU,EAAE,gEAAgE;KAC7E,CAAC;IAEF,WAAW,CAAC,OAAe,EAAE,KAAa,EAAE,GAAW;QACrD,OAAO,IAAI,CAAC,WAAW,CAAC,aAAa,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;IAClE,CAAC;IAED,YAAY,CAAC,IAAe,EAAE,OAAe;QAC3C,OAAO,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACzC,CAAC;IAED,WAAW,CACT,IAAe,EACf,OAAe,EACf,QAAmB;QAEnB,OAAO;YACL,OAAO,EAAE,KAAK;YACd,KAAK,EAAE;gBACL,IAAI;gBACJ,OAAO;gBACP,QAAQ;gBACR,UAAU,EAAE,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC;aACnC;SACF,CAAC;IACJ,CAAC;IAED,OAAO,CAAC,MAAc,EAAE,OAAoC;QAC1D,OAAO;YACL,OAAO,EAAE,IAAI;YACb,MAAM;YACN,OAAO;SACR,CAAC;IACJ,CAAC;CACF"}
@@ -0,0 +1,25 @@
1
+ export type ErrorType = 'SyntaxError' | 'DivisionByZero' | 'InvalidNumber' | 'OverflowError' | 'InvalidBase' | 'UnmatchedParen' | 'InvalidOperator' | 'EmptyInput';
2
+ export interface Position {
3
+ start: number;
4
+ end: number;
5
+ }
6
+ export interface ErrorDetail {
7
+ type: ErrorType;
8
+ message: string;
9
+ position?: Position;
10
+ suggestion: string;
11
+ }
12
+ export interface SuccessResponse {
13
+ success: true;
14
+ result: string;
15
+ details?: {
16
+ expression?: string;
17
+ steps?: string[];
18
+ };
19
+ }
20
+ export interface ErrorResponse {
21
+ success: false;
22
+ error: ErrorDetail;
23
+ }
24
+ export type CalculationResponse = SuccessResponse | ErrorResponse;
25
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/errors/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,SAAS,GACjB,aAAa,GACb,gBAAgB,GAChB,eAAe,GACf,eAAe,GACf,aAAa,GACb,gBAAgB,GAChB,iBAAiB,GACjB,YAAY,CAAC;AAEjB,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,SAAS,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,IAAI,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE;QACR,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;KAClB,CAAC;CACH;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,KAAK,CAAC;IACf,KAAK,EAAE,WAAW,CAAC;CACpB;AAED,MAAM,MAAM,mBAAmB,GAAG,eAAe,GAAG,aAAa,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/errors/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/build/index.js ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env node
2
+ import { createMCPServer } from './mcp/server.js';
3
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
4
+ async function main() {
5
+ const server = createMCPServer();
6
+ const transport = new StdioServerTransport();
7
+ await server.connect(transport);
8
+ // eslint-disable-next-line no-console
9
+ console.error('MCP Calculator server running on stdio');
10
+ }
11
+ main().catch((error) => {
12
+ // eslint-disable-next-line no-console
13
+ console.error('Fatal error:', error);
14
+ process.exit(1);
15
+ });
16
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AAEjF,KAAK,UAAU,IAAI;IACjB,MAAM,MAAM,GAAG,eAAe,EAAE,CAAC;IACjC,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAE7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAEhC,sCAAsC;IACtC,OAAO,CAAC,KAAK,CAAC,wCAAwC,CAAC,CAAC;AAC1D,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACrB,sCAAsC;IACtC,OAAO,CAAC,KAAK,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC;IACrC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
2
+ export declare function createMCPServer(): Server;
3
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAsGnE,wBAAgB,eAAe,IAAI,MAAM,CAwLxC"}