@tokcalc/mcp-server 0.1.2 → 0.1.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.
Files changed (192) hide show
  1. package/README.md +86 -406
  2. package/dist/index.js +21285 -0
  3. package/package.json +34 -91
  4. package/.zscripts/build.sh +0 -175
  5. package/.zscripts/database-runtime-build.sh +0 -33
  6. package/.zscripts/dev.pid +0 -1
  7. package/.zscripts/dev.sh +0 -154
  8. package/.zscripts/mini-services-build.sh +0 -78
  9. package/.zscripts/mini-services-install.sh +0 -65
  10. package/.zscripts/mini-services-start.sh +0 -123
  11. package/.zscripts/python-runtime-build.sh +0 -120
  12. package/.zscripts/start.sh +0 -145
  13. package/CAPACITY_STUDY.md +0 -283
  14. package/CODE_OF_CONDUCT.md +0 -55
  15. package/CONTRIBUTING.md +0 -177
  16. package/Caddyfile +0 -23
  17. package/LICENSE +0 -204
  18. package/bun.lock +0 -1965
  19. package/components.json +0 -21
  20. package/db/custom.db +0 -0
  21. package/download/README.md +0 -1
  22. package/download/tokcalc-dark-calculator.png +0 -0
  23. package/download/tokcalc-dark-default.png +0 -0
  24. package/download/tokcalc-demo.webm +0 -0
  25. package/download/tokcalc-github-link.png +0 -0
  26. package/download/tokcalc-hydration-fixed.png +0 -0
  27. package/download/tokcalc-issue-resolved.png +0 -0
  28. package/download/tokcalc-light-mode.png +0 -0
  29. package/download/tokcalc-light-reference.png +0 -0
  30. package/download/tokcalc-long-context-qwen.png +0 -0
  31. package/download/tokcalc-long-context.png +0 -0
  32. package/download/tokcalc-og-image-preview.png +0 -0
  33. package/download/tokcalc-phase2-3.png +0 -0
  34. package/download/tokcalc-plain-english.png +0 -0
  35. package/download/tokcalc-preview.png +0 -0
  36. package/download/tokcalc-share-bvb.png +0 -0
  37. package/download/tokcalc-share-feature.png +0 -0
  38. package/download/tokcalc-tab-build-vs-buy.png +0 -0
  39. package/download/tokcalc-tab-calculator.png +0 -0
  40. package/download/tokcalc-tab-reference.png +0 -0
  41. package/eslint.config.mjs +0 -50
  42. package/examples/websocket/frontend.tsx +0 -196
  43. package/examples/websocket/server.ts +0 -138
  44. package/mini-services/.gitkeep +0 -0
  45. package/mini-services/mcp-server/README.md +0 -86
  46. package/mini-services/mcp-server/bun.lock +0 -202
  47. package/mini-services/mcp-server/index.ts +0 -504
  48. package/mini-services/mcp-server/package.json +0 -40
  49. package/next.config.ts +0 -12
  50. package/postcss.config.mjs +0 -5
  51. package/prisma/schema.prisma +0 -32
  52. package/public/google6f58ca6be85fa903.html +0 -1
  53. package/public/logo.svg +0 -29
  54. package/public/manifest.json +0 -51
  55. package/public/og-icon-256.png +0 -0
  56. package/public/og.png +0 -0
  57. package/public/robots.txt +0 -25
  58. package/public/sitemap.xml +0 -23
  59. package/public/tokcalc-demo.gif +0 -0
  60. package/scripts/og-template.html +0 -120
  61. package/scripts/render-og.mjs +0 -43
  62. package/server.json +0 -21
  63. package/src/app/api/pricing/aws/route.ts +0 -186
  64. package/src/app/api/pricing/azure/route.ts +0 -168
  65. package/src/app/api/pricing/gcp/route.ts +0 -230
  66. package/src/app/api/pricing/vast-ai/route.ts +0 -164
  67. package/src/app/api/route.ts +0 -5
  68. package/src/app/compare/h100-vs-h200/layout.tsx +0 -30
  69. package/src/app/compare/h100-vs-h200/page.tsx +0 -328
  70. package/src/app/globals.css +0 -122
  71. package/src/app/layout.tsx +0 -276
  72. package/src/app/page.tsx +0 -2670
  73. package/src/components/azure-live-pricing.tsx +0 -185
  74. package/src/components/benchmark-import.tsx +0 -340
  75. package/src/components/confidence-badge.tsx +0 -116
  76. package/src/components/live-pricing-comparison.tsx +0 -241
  77. package/src/components/theme-provider.tsx +0 -11
  78. package/src/components/theme-toggle.tsx +0 -55
  79. package/src/components/ui/accordion.tsx +0 -66
  80. package/src/components/ui/alert-dialog.tsx +0 -157
  81. package/src/components/ui/alert.tsx +0 -66
  82. package/src/components/ui/aspect-ratio.tsx +0 -11
  83. package/src/components/ui/avatar.tsx +0 -53
  84. package/src/components/ui/badge.tsx +0 -46
  85. package/src/components/ui/breadcrumb.tsx +0 -109
  86. package/src/components/ui/button.tsx +0 -59
  87. package/src/components/ui/calendar.tsx +0 -213
  88. package/src/components/ui/card.tsx +0 -92
  89. package/src/components/ui/carousel.tsx +0 -241
  90. package/src/components/ui/chart.tsx +0 -353
  91. package/src/components/ui/checkbox.tsx +0 -32
  92. package/src/components/ui/collapsible.tsx +0 -33
  93. package/src/components/ui/command.tsx +0 -184
  94. package/src/components/ui/context-menu.tsx +0 -252
  95. package/src/components/ui/dialog.tsx +0 -143
  96. package/src/components/ui/drawer.tsx +0 -135
  97. package/src/components/ui/dropdown-menu.tsx +0 -257
  98. package/src/components/ui/form.tsx +0 -167
  99. package/src/components/ui/hover-card.tsx +0 -44
  100. package/src/components/ui/input-otp.tsx +0 -77
  101. package/src/components/ui/input.tsx +0 -21
  102. package/src/components/ui/label.tsx +0 -24
  103. package/src/components/ui/menubar.tsx +0 -276
  104. package/src/components/ui/navigation-menu.tsx +0 -168
  105. package/src/components/ui/pagination.tsx +0 -127
  106. package/src/components/ui/popover.tsx +0 -48
  107. package/src/components/ui/progress.tsx +0 -31
  108. package/src/components/ui/radio-group.tsx +0 -45
  109. package/src/components/ui/resizable.tsx +0 -56
  110. package/src/components/ui/scroll-area.tsx +0 -58
  111. package/src/components/ui/select.tsx +0 -185
  112. package/src/components/ui/separator.tsx +0 -28
  113. package/src/components/ui/sheet.tsx +0 -139
  114. package/src/components/ui/sidebar.tsx +0 -726
  115. package/src/components/ui/skeleton.tsx +0 -13
  116. package/src/components/ui/slider.tsx +0 -63
  117. package/src/components/ui/sonner.tsx +0 -25
  118. package/src/components/ui/switch.tsx +0 -31
  119. package/src/components/ui/table.tsx +0 -116
  120. package/src/components/ui/tabs.tsx +0 -66
  121. package/src/components/ui/textarea.tsx +0 -18
  122. package/src/components/ui/toast.tsx +0 -129
  123. package/src/components/ui/toaster.tsx +0 -35
  124. package/src/components/ui/toggle-group.tsx +0 -73
  125. package/src/components/ui/toggle.tsx +0 -47
  126. package/src/components/ui/tooltip.tsx +0 -61
  127. package/src/components/vast-ai-live-pricing.tsx +0 -176
  128. package/src/hooks/use-mobile.ts +0 -19
  129. package/src/hooks/use-toast.ts +0 -194
  130. package/src/lib/benchmark-parser-sglang.ts +0 -150
  131. package/src/lib/benchmark-parser-tokcalc.ts +0 -247
  132. package/src/lib/benchmark-parser-trtllm.ts +0 -152
  133. package/src/lib/benchmark-parser-vllm.ts +0 -198
  134. package/src/lib/benchmark-schema.ts +0 -263
  135. package/src/lib/db.ts +0 -13
  136. package/src/lib/engine-presets.ts +0 -183
  137. package/src/lib/price-schema.ts +0 -141
  138. package/src/lib/token-calc.ts +0 -808
  139. package/src/lib/track.ts +0 -31
  140. package/src/lib/url-state.ts +0 -256
  141. package/src/lib/utils.ts +0 -6
  142. package/tailwind.config.ts +0 -64
  143. package/tests/database-runtime-build.sh +0 -75
  144. package/tests/python-runtime-build.sh +0 -64
  145. package/tests/python-runtime-container.sh +0 -31
  146. package/tool-results/bash_1789888171144_2c5381860539.txt +0 -161
  147. package/tool-results/bash_1789888175925_49c53ba3c61b.txt +0 -191
  148. package/tool-results/bash_1789888181202_49c53ba3c61b.txt +0 -191
  149. package/tool-results/bash_1789888195219_4a86a5c91411.txt +0 -200
  150. package/tool-results/bash_1789888203128_6cca13c71b47.txt +0 -199
  151. package/tool-results/bash_1789929256963_2a52aff0d0a8.txt +0 -160
  152. package/tool-results/read_1789888151021_69f58eec6a5b.txt +0 -653
  153. package/tool-results/read_1789888153837_1d3a8bfc2a94.txt +0 -653
  154. package/tool-results/read_1789888163087_ccc406d47505.txt +0 -122
  155. package/tool-results/read_1789888167347_67d1d7c9830a.txt +0 -122
  156. package/tool-results/read_1789929252529_d90e8f383a25.txt +0 -285
  157. package/tsconfig.json +0 -42
  158. package/upload/Pasted Content_1789887800864.txt +0 -652
  159. package/upload/Pasted Content_1789887909561.txt +0 -652
  160. package/upload/Pasted Content_1789887918428.txt +0 -652
  161. package/upload/Pasted Content_1789887959420.txt +0 -652
  162. package/upload/Pasted Content_1789888020485.txt +0 -652
  163. package/upload/Pasted Content_1789888058079.txt +0 -652
  164. package/upload/Pasted Content_1789888885033.txt +0 -686
  165. package/upload/Pasted Content_1789928912741.txt +0 -285
  166. package/upload/Pasted Content_1789928938402.txt +0 -285
  167. package/upload/Pasted Content_1789929160389.txt +0 -285
  168. package/upload/Pasted Content_1789929176660.txt +0 -285
  169. package/upload/issue_vision.json +0 -28
  170. package/upload/pasted_image_1789883175209.png +0 -0
  171. package/upload/pasted_image_1789899056690.png +0 -0
  172. package/upload/pasted_image_1789900371483.png +0 -0
  173. package/upload/pasted_image_1789900472823.png +0 -0
  174. package/upload/pasted_image_1789900490374.png +0 -0
  175. package/upload/pasted_image_1789900585552.png +0 -0
  176. package/upload/pasted_image_1789900606519.png +0 -0
  177. package/upload/pasted_image_1789901598705.png +0 -0
  178. package/upload/pasted_image_1789901613545.png +0 -0
  179. package/upload/pasted_image_1789978382674.png +0 -0
  180. package/upload/pasted_image_1789978392749.png +0 -0
  181. package/upload/pasted_image_1789978474879.png +0 -0
  182. package/upload/pasted_image_1789978523652.png +0 -0
  183. package/upload/pasted_image_1789984219089.png +0 -0
  184. package/upload/pasted_image_1789984491896.png +0 -0
  185. package/upload/pasted_image_1789985017950.png +0 -0
  186. package/upload/pasted_image_1789985036765.png +0 -0
  187. package/upload/pasted_image_1789985049848.png +0 -0
  188. package/upload/pasted_image_1790002427833.png +0 -0
  189. package/upload/pasted_image_1790002659944.png +0 -0
  190. package/upload/pasted_image_1790037038476.png +0 -0
  191. package/upload/screenshot_analysis.json +0 -28
  192. package/upload/vision_output.json +0 -28
package/components.json DELETED
@@ -1,21 +0,0 @@
1
- {
2
- "$schema": "https://ui.shadcn.com/schema.json",
3
- "style": "new-york",
4
- "rsc": true,
5
- "tsx": true,
6
- "tailwind": {
7
- "config": "",
8
- "css": "src/app/globals.css",
9
- "baseColor": "neutral",
10
- "cssVariables": true,
11
- "prefix": ""
12
- },
13
- "aliases": {
14
- "components": "@/components",
15
- "utils": "@/lib/utils",
16
- "ui": "@/components/ui",
17
- "lib": "@/lib",
18
- "hooks": "@/hooks"
19
- },
20
- "iconLibrary": "lucide"
21
- }
package/db/custom.db DELETED
Binary file
@@ -1 +0,0 @@
1
- Here are all the generated files.
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
package/eslint.config.mjs DELETED
@@ -1,50 +0,0 @@
1
- import nextCoreWebVitals from "eslint-config-next/core-web-vitals";
2
- import nextTypescript from "eslint-config-next/typescript";
3
- import { dirname } from "path";
4
- import { fileURLToPath } from "url";
5
-
6
- const __filename = fileURLToPath(import.meta.url);
7
- const __dirname = dirname(__filename);
8
-
9
- const eslintConfig = [...nextCoreWebVitals, ...nextTypescript, {
10
- rules: {
11
- // TypeScript rules
12
- "@typescript-eslint/no-explicit-any": "off",
13
- "@typescript-eslint/no-unused-vars": "off",
14
- "@typescript-eslint/no-non-null-assertion": "off",
15
- "@typescript-eslint/ban-ts-comment": "off",
16
- "@typescript-eslint/prefer-as-const": "off",
17
- "@typescript-eslint/no-unused-disable-directive": "off",
18
-
19
- // React rules
20
- "react-hooks/exhaustive-deps": "off",
21
- "react-hooks/purity": "off",
22
- "react/no-unescaped-entities": "off",
23
- "react/display-name": "off",
24
- "react/prop-types": "off",
25
- "react-compiler/react-compiler": "off",
26
-
27
- // Next.js rules
28
- "@next/next/no-img-element": "off",
29
- "@next/next/no-html-link-for-pages": "off",
30
-
31
- // General JavaScript rules
32
- "prefer-const": "off",
33
- "no-unused-vars": "off",
34
- "no-console": "off",
35
- "no-debugger": "off",
36
- "no-empty": "off",
37
- "no-irregular-whitespace": "off",
38
- "no-case-declarations": "off",
39
- "no-fallthrough": "off",
40
- "no-mixed-spaces-and-tabs": "off",
41
- "no-redeclare": "off",
42
- "no-undef": "off",
43
- "no-unreachable": "off",
44
- "no-useless-escape": "off",
45
- },
46
- }, {
47
- ignores: ["node_modules/**", ".next/**", "out/**", "build/**", "next-env.d.ts", "examples/**", "skills", "mini-services/mcp-server/dist/**"]
48
- }];
49
-
50
- export default eslintConfig;
@@ -1,196 +0,0 @@
1
- 'use client';
2
-
3
- import { useEffect, useState } from 'react';
4
- import { io } from 'socket.io-client';
5
- import { Button } from '@/components/ui/button';
6
- import { Input } from '@/components/ui/input';
7
- import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
8
- import { ScrollArea } from '@/components/ui/scroll-area';
9
-
10
- type User = {
11
- id: string;
12
- username: string;
13
- }
14
-
15
- type Message = {
16
- id: string;
17
- username: string;
18
- content: string;
19
- timestamp: Date | string;
20
- type: 'user' | 'system';
21
- }
22
-
23
- export default function SocketDemo() {
24
- const [messages, setMessages] = useState<Message[]>([]);
25
- const [inputMessage, setInputMessage] = useState('');
26
- const [username, setUsername] = useState('');
27
- const [isUsernameSet, setIsUsernameSet] = useState(false);
28
- const [socket, setSocket] = useState<any>(null);
29
- const [isConnected, setIsConnected] = useState(false);
30
- const [users, setUsers] = useState<User[]>([]);
31
-
32
- useEffect(() => {
33
- // Connect to websocket server
34
- // Never use PORT in the URL, alyways use XTransformPort
35
- // DO NOT change the path, it is used by Caddy to forward the request to the correct port
36
- const socketInstance = io('/?XTransformPort=3003', {
37
- transports: ['websocket', 'polling'],
38
- forceNew: true,
39
- reconnection: true,
40
- reconnectionAttempts: 5,
41
- reconnectionDelay: 1000,
42
- timeout: 10000
43
- })
44
-
45
- setSocket(socketInstance);
46
-
47
- socketInstance.on('connect', () => {
48
- setIsConnected(true);
49
- });
50
-
51
- socketInstance.on('disconnect', () => {
52
- setIsConnected(false);
53
- });
54
-
55
- socketInstance.on('message', (msg: Message) => {
56
- setMessages(prev => [...prev, msg]);
57
- });
58
-
59
- socketInstance.on('user-joined', (data: { user: User; message: Message }) => {
60
- setMessages(prev => [...prev, data.message]);
61
- setUsers(prev => {
62
- if (!prev.find(u => u.id === data.user.id)) {
63
- return [...prev, data.user];
64
- }
65
- return prev;
66
- });
67
- });
68
-
69
- socketInstance.on('user-left', (data: { user: User; message: Message }) => {
70
- setMessages(prev => [...prev, data.message]);
71
- setUsers(prev => prev.filter(u => u.id !== data.user.id));
72
- });
73
-
74
- socketInstance.on('users-list', (data: { users: User[] }) => {
75
- setUsers(data.users);
76
- });
77
-
78
- return () => {
79
- socketInstance.disconnect();
80
- };
81
- }, []);
82
-
83
- const handleJoin = () => {
84
- if (socket && username.trim() && isConnected) {
85
- socket.emit('join', { username: username.trim() });
86
- setIsUsernameSet(true);
87
- }
88
- };
89
-
90
- const sendMessage = () => {
91
- if (socket && inputMessage.trim() && username.trim()) {
92
- socket.emit('message', {
93
- content: inputMessage.trim(),
94
- username: username.trim()
95
- });
96
- setInputMessage('');
97
- }
98
- };
99
-
100
- const handleKeyPress = (e: React.KeyboardEvent) => {
101
- if (e.key === 'Enter') {
102
- sendMessage();
103
- }
104
- };
105
-
106
- return (
107
- <div className="container mx-auto p-4 max-w-2xl">
108
- <Card>
109
- <CardHeader>
110
- <CardTitle className="flex items-center justify-between">
111
- WebSocket Demo
112
- <span className={`text-sm px-2 py-1 rounded ${isConnected ? 'bg-green-100 text-green-800' : 'bg-red-100 text-red-800'}`}>
113
- {isConnected ? 'Connected' : 'Disconnected'}
114
- </span>
115
- </CardTitle>
116
- </CardHeader>
117
- <CardContent className="space-y-4">
118
- {!isUsernameSet ? (
119
- <div className="space-y-2">
120
- <Input
121
- value={username}
122
- onChange={(e) => setUsername(e.target.value)}
123
- onKeyPress={(e) => {
124
- if (e.key === 'Enter') {
125
- handleJoin();
126
- }
127
- }}
128
- placeholder="Enter your username..."
129
- disabled={!isConnected}
130
- className="flex-1"
131
- />
132
- <Button
133
- onClick={handleJoin}
134
- disabled={!isConnected || !username.trim()}
135
- className="w-full"
136
- >
137
- Join Chat
138
- </Button>
139
- </div>
140
- ) : (
141
- <>
142
- <ScrollArea className="h-80 w-full border rounded-md p-4">
143
- <div className="space-y-2">
144
- {messages.length === 0 ? (
145
- <p className="text-gray-500 text-center">No messages yet</p>
146
- ) : (
147
- messages.map((msg) => (
148
- <div key={msg.id} className="border-b pb-2 last:border-b-0">
149
- <div className="flex justify-between items-start">
150
- <div className="flex-1">
151
- <p className={`text-sm font-medium ${msg.type === 'system'
152
- ? 'text-blue-600 italic'
153
- : 'text-gray-700'
154
- }`}>
155
- {msg.username}
156
- </p>
157
- <p className={`${msg.type === 'system'
158
- ? 'text-blue-500 italic'
159
- : 'text-gray-900'
160
- }`}>
161
- {msg.content}
162
- </p>
163
- </div>
164
- <span className="text-xs text-gray-500">
165
- {new Date(msg.timestamp).toLocaleTimeString()}
166
- </span>
167
- </div>
168
- </div>
169
- ))
170
- )}
171
- </div>
172
- </ScrollArea>
173
-
174
- <div className="flex space-x-2">
175
- <Input
176
- value={inputMessage}
177
- onChange={(e) => setInputMessage(e.target.value)}
178
- onKeyPress={handleKeyPress}
179
- placeholder="Type a message..."
180
- disabled={!isConnected}
181
- className="flex-1"
182
- />
183
- <Button
184
- onClick={sendMessage}
185
- disabled={!isConnected || !inputMessage.trim()}
186
- >
187
- Send
188
- </Button>
189
- </div>
190
- </>
191
- )}
192
- </CardContent>
193
- </Card>
194
- </div>
195
- );
196
- }
@@ -1,138 +0,0 @@
1
- import { createServer } from 'http'
2
- import { Server } from 'socket.io'
3
-
4
- const httpServer = createServer()
5
- const io = new Server(httpServer, {
6
- // DO NOT change the path, it is used by Caddy to forward the request to the correct port
7
- path: '/',
8
- cors: {
9
- origin: "*",
10
- methods: ["GET", "POST"]
11
- },
12
- pingTimeout: 60000,
13
- pingInterval: 25000,
14
- })
15
-
16
- interface User {
17
- id: string
18
- username: string
19
- }
20
-
21
- interface Message {
22
- id: string
23
- username: string
24
- content: string
25
- timestamp: Date
26
- type: 'user' | 'system'
27
- }
28
-
29
- const users = new Map<string, User>()
30
-
31
- const generateMessageId = () => Math.random().toString(36).substr(2, 9)
32
-
33
- const createSystemMessage = (content: string): Message => ({
34
- id: generateMessageId(),
35
- username: 'System',
36
- content,
37
- timestamp: new Date(),
38
- type: 'system'
39
- })
40
-
41
- const createUserMessage = (username: string, content: string): Message => ({
42
- id: generateMessageId(),
43
- username,
44
- content,
45
- timestamp: new Date(),
46
- type: 'user'
47
- })
48
-
49
- io.on('connection', (socket) => {
50
- console.log(`User connected: ${socket.id}`)
51
-
52
- // Add test event handler
53
- socket.on('test', (data) => {
54
- console.log('Received test message:', data)
55
- socket.emit('test-response', {
56
- message: 'Server received test message',
57
- data: data,
58
- timestamp: new Date().toISOString()
59
- })
60
- })
61
-
62
- socket.on('join', (data: { username: string }) => {
63
- const { username } = data
64
-
65
- // Create user object
66
- const user: User = {
67
- id: socket.id,
68
- username
69
- }
70
-
71
- // Add to user list
72
- users.set(socket.id, user)
73
-
74
- // Send join message to all users
75
- const joinMessage = createSystemMessage(`${username} joined the chat room`)
76
- io.emit('user-joined', { user, message: joinMessage })
77
-
78
- // Send current user list to new user
79
- const usersList = Array.from(users.values())
80
- socket.emit('users-list', { users: usersList })
81
-
82
- console.log(`${username} joined the chat room, current online users: ${users.size}`)
83
- })
84
-
85
- socket.on('message', (data: { content: string; username: string }) => {
86
- const { content, username } = data
87
- const user = users.get(socket.id)
88
-
89
- if (user && user.username === username) {
90
- const message = createUserMessage(username, content)
91
- io.emit('message', message)
92
- console.log(`${username}: ${content}`)
93
- }
94
- })
95
-
96
- socket.on('disconnect', () => {
97
- const user = users.get(socket.id)
98
-
99
- if (user) {
100
- // Remove from user list
101
- users.delete(socket.id)
102
-
103
- // Send leave message to all users
104
- const leaveMessage = createSystemMessage(`${user.username} left the chat room`)
105
- io.emit('user-left', { user: { id: socket.id, username: user.username }, message: leaveMessage })
106
-
107
- console.log(`${user.username} left the chat room, current online users: ${users.size}`)
108
- } else {
109
- console.log(`User disconnected: ${socket.id}`)
110
- }
111
- })
112
-
113
- socket.on('error', (error) => {
114
- console.error(`Socket error (${socket.id}):`, error)
115
- })
116
- })
117
-
118
- const PORT = 3003
119
- httpServer.listen(PORT, () => {
120
- console.log(`WebSocket server running on port ${PORT}`)
121
- })
122
-
123
- // Graceful shutdown
124
- process.on('SIGTERM', () => {
125
- console.log('Received SIGTERM signal, shutting down server...')
126
- httpServer.close(() => {
127
- console.log('WebSocket server closed')
128
- process.exit(0)
129
- })
130
- })
131
-
132
- process.on('SIGINT', () => {
133
- console.log('Received SIGINT signal, shutting down server...')
134
- httpServer.close(() => {
135
- console.log('WebSocket server closed')
136
- process.exit(0)
137
- })
138
- })
File without changes
@@ -1,86 +0,0 @@
1
- # @tokcalc/mcp-server
2
-
3
- **LLM serving capacity planner for AI agents.**
4
-
5
- Open-source MCP (Model Context Protocol) server that lets AI agents (Cursor, Claude Desktop, Cline) estimate LLM serving capacity — model fit, KV cache, throughput, latency, multi-GPU topology, and cost.
6
-
7
- ## Tools
8
-
9
- | Tool | What it does |
10
- |---|---|
11
- | `estimate_capacity` | VRAM/KV/throughput/latency/cost for one config |
12
- | `compare_gpus` | Ranked GPU comparison for one workload |
13
- | `recommend_topology` | TP/CP topology recommendation |
14
- | `estimate_api_vs_self_host` | Break-even analysis |
15
- | `list_models` | Discover supported model IDs (35 models) |
16
- | `list_gpus` | Discover supported GPU IDs (30 GPUs) |
17
-
18
- All tools are **read-only** — no side effects, no cloud credentials, no deployments.
19
-
20
- ## Install
21
-
22
- ### Claude Desktop
23
-
24
- Add to `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows):
25
-
26
- ```json
27
- {
28
- "mcpServers": {
29
- "tokcalc": {
30
- "command": "npx",
31
- "args": ["-y", "@tokcalc/mcp-server"]
32
- }
33
- }
34
- }
35
- ```
36
-
37
- Restart Claude Desktop. The `tokcalc` server will be available as an MCP tool source.
38
-
39
- ### Cursor
40
-
41
- Add to `.cursor/mcp.json` in your project:
42
-
43
- ```json
44
- {
45
- "mcpServers": {
46
- "tokcalc": {
47
- "command": "npx",
48
- "args": ["-y", "@tokcalc/mcp-server"]
49
- }
50
- }
51
- }
52
- ```
53
-
54
- ### Cline (VS Code)
55
-
56
- Add the same config to Cline's MCP settings.
57
-
58
- ## Example prompts
59
-
60
- Ask your AI agent:
61
-
62
- > "I need to serve Llama 3.3 70B at 32K context for 50 concurrent users. What GPU topology do you recommend, and how much will it cost per month?"
63
-
64
- > "Compare H100 vs H200 for serving Qwen 2.5 72B in FP8 with continuous batching."
65
-
66
- > "At what daily request volume does self-hosting Llama 70B on H200 beat the GPT-4o API?"
67
-
68
- The agent calls `list_models` → `list_gpus` → `recommend_topology` → `estimate_capacity` and returns a structured plan with throughput ranges, latency, VRAM, cost, and confidence levels.
69
-
70
- ## Supported models (35)
71
-
72
- Llama 3/3.1/3.3, Llama 4 Scout/Maverick, Mistral 7B, Mixtral 8x7B/8x22B, Mistral Large 3, Pixtral 12B, Codestral, Qwen 2/2.5/3 (incl. MoE + VL), DeepSeek V3/R1/Coder V2, Gemma 2, Phi-3/4, SmolLM2, Falcon 3, OLMo 2, BGE-M3, E5, GTE.
73
-
74
- ## Supported GPUs (30)
75
-
76
- NVIDIA H100/H200/B200/B300, A100, L40S, L4, T4, V100, RTX 4090/3090/5090, RTX PRO 6000 Blackwell, AMD MI300X/MI325X, Intel Gaudi 3, Google TPU v5p/Trillium, Groq LPU, Cerebras CS-3, Apple M2/M3/M4 Ultra/Max.
77
-
78
- ## License
79
-
80
- Apache 2.0 — same as the main tokcalc project.
81
-
82
- ## Links
83
-
84
- - [Live calculator](https://tokcalc.vercel.app)
85
- - [GitHub](https://github.com/stevecrates489-commits/tokcalc)
86
- - [CONTRIBUTING](https://github.com/stevecrates489-commits/tokcalc/blob/main/CONTRIBUTING.md)