@tokcalc/mcp-server 0.1.3 → 0.2.0-alpha.1

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 (193) hide show
  1. package/README.md +86 -406
  2. package/dist/http.js +23504 -0
  3. package/dist/index.js +21290 -0
  4. package/package.json +36 -92
  5. package/.zscripts/build.sh +0 -175
  6. package/.zscripts/database-runtime-build.sh +0 -33
  7. package/.zscripts/dev.pid +0 -1
  8. package/.zscripts/dev.sh +0 -154
  9. package/.zscripts/mini-services-build.sh +0 -78
  10. package/.zscripts/mini-services-install.sh +0 -65
  11. package/.zscripts/mini-services-start.sh +0 -123
  12. package/.zscripts/python-runtime-build.sh +0 -120
  13. package/.zscripts/start.sh +0 -145
  14. package/CAPACITY_STUDY.md +0 -283
  15. package/CODE_OF_CONDUCT.md +0 -55
  16. package/CONTRIBUTING.md +0 -177
  17. package/Caddyfile +0 -23
  18. package/LICENSE +0 -204
  19. package/bun.lock +0 -1965
  20. package/components.json +0 -21
  21. package/db/custom.db +0 -0
  22. package/download/README.md +0 -1
  23. package/download/tokcalc-dark-calculator.png +0 -0
  24. package/download/tokcalc-dark-default.png +0 -0
  25. package/download/tokcalc-demo.webm +0 -0
  26. package/download/tokcalc-github-link.png +0 -0
  27. package/download/tokcalc-hydration-fixed.png +0 -0
  28. package/download/tokcalc-issue-resolved.png +0 -0
  29. package/download/tokcalc-light-mode.png +0 -0
  30. package/download/tokcalc-light-reference.png +0 -0
  31. package/download/tokcalc-long-context-qwen.png +0 -0
  32. package/download/tokcalc-long-context.png +0 -0
  33. package/download/tokcalc-og-image-preview.png +0 -0
  34. package/download/tokcalc-phase2-3.png +0 -0
  35. package/download/tokcalc-plain-english.png +0 -0
  36. package/download/tokcalc-preview.png +0 -0
  37. package/download/tokcalc-share-bvb.png +0 -0
  38. package/download/tokcalc-share-feature.png +0 -0
  39. package/download/tokcalc-tab-build-vs-buy.png +0 -0
  40. package/download/tokcalc-tab-calculator.png +0 -0
  41. package/download/tokcalc-tab-reference.png +0 -0
  42. package/eslint.config.mjs +0 -50
  43. package/examples/websocket/frontend.tsx +0 -196
  44. package/examples/websocket/server.ts +0 -138
  45. package/mini-services/.gitkeep +0 -0
  46. package/mini-services/mcp-server/README.md +0 -86
  47. package/mini-services/mcp-server/bun.lock +0 -202
  48. package/mini-services/mcp-server/index.ts +0 -504
  49. package/mini-services/mcp-server/package.json +0 -40
  50. package/next.config.ts +0 -12
  51. package/postcss.config.mjs +0 -5
  52. package/prisma/schema.prisma +0 -32
  53. package/public/google6f58ca6be85fa903.html +0 -1
  54. package/public/logo.svg +0 -29
  55. package/public/manifest.json +0 -51
  56. package/public/og-icon-256.png +0 -0
  57. package/public/og.png +0 -0
  58. package/public/robots.txt +0 -25
  59. package/public/sitemap.xml +0 -23
  60. package/public/tokcalc-demo.gif +0 -0
  61. package/scripts/og-template.html +0 -120
  62. package/scripts/render-og.mjs +0 -43
  63. package/server.json +0 -21
  64. package/src/app/api/pricing/aws/route.ts +0 -186
  65. package/src/app/api/pricing/azure/route.ts +0 -168
  66. package/src/app/api/pricing/gcp/route.ts +0 -230
  67. package/src/app/api/pricing/vast-ai/route.ts +0 -164
  68. package/src/app/api/route.ts +0 -5
  69. package/src/app/compare/h100-vs-h200/layout.tsx +0 -30
  70. package/src/app/compare/h100-vs-h200/page.tsx +0 -328
  71. package/src/app/globals.css +0 -122
  72. package/src/app/layout.tsx +0 -276
  73. package/src/app/page.tsx +0 -2670
  74. package/src/components/azure-live-pricing.tsx +0 -185
  75. package/src/components/benchmark-import.tsx +0 -340
  76. package/src/components/confidence-badge.tsx +0 -116
  77. package/src/components/live-pricing-comparison.tsx +0 -241
  78. package/src/components/theme-provider.tsx +0 -11
  79. package/src/components/theme-toggle.tsx +0 -55
  80. package/src/components/ui/accordion.tsx +0 -66
  81. package/src/components/ui/alert-dialog.tsx +0 -157
  82. package/src/components/ui/alert.tsx +0 -66
  83. package/src/components/ui/aspect-ratio.tsx +0 -11
  84. package/src/components/ui/avatar.tsx +0 -53
  85. package/src/components/ui/badge.tsx +0 -46
  86. package/src/components/ui/breadcrumb.tsx +0 -109
  87. package/src/components/ui/button.tsx +0 -59
  88. package/src/components/ui/calendar.tsx +0 -213
  89. package/src/components/ui/card.tsx +0 -92
  90. package/src/components/ui/carousel.tsx +0 -241
  91. package/src/components/ui/chart.tsx +0 -353
  92. package/src/components/ui/checkbox.tsx +0 -32
  93. package/src/components/ui/collapsible.tsx +0 -33
  94. package/src/components/ui/command.tsx +0 -184
  95. package/src/components/ui/context-menu.tsx +0 -252
  96. package/src/components/ui/dialog.tsx +0 -143
  97. package/src/components/ui/drawer.tsx +0 -135
  98. package/src/components/ui/dropdown-menu.tsx +0 -257
  99. package/src/components/ui/form.tsx +0 -167
  100. package/src/components/ui/hover-card.tsx +0 -44
  101. package/src/components/ui/input-otp.tsx +0 -77
  102. package/src/components/ui/input.tsx +0 -21
  103. package/src/components/ui/label.tsx +0 -24
  104. package/src/components/ui/menubar.tsx +0 -276
  105. package/src/components/ui/navigation-menu.tsx +0 -168
  106. package/src/components/ui/pagination.tsx +0 -127
  107. package/src/components/ui/popover.tsx +0 -48
  108. package/src/components/ui/progress.tsx +0 -31
  109. package/src/components/ui/radio-group.tsx +0 -45
  110. package/src/components/ui/resizable.tsx +0 -56
  111. package/src/components/ui/scroll-area.tsx +0 -58
  112. package/src/components/ui/select.tsx +0 -185
  113. package/src/components/ui/separator.tsx +0 -28
  114. package/src/components/ui/sheet.tsx +0 -139
  115. package/src/components/ui/sidebar.tsx +0 -726
  116. package/src/components/ui/skeleton.tsx +0 -13
  117. package/src/components/ui/slider.tsx +0 -63
  118. package/src/components/ui/sonner.tsx +0 -25
  119. package/src/components/ui/switch.tsx +0 -31
  120. package/src/components/ui/table.tsx +0 -116
  121. package/src/components/ui/tabs.tsx +0 -66
  122. package/src/components/ui/textarea.tsx +0 -18
  123. package/src/components/ui/toast.tsx +0 -129
  124. package/src/components/ui/toaster.tsx +0 -35
  125. package/src/components/ui/toggle-group.tsx +0 -73
  126. package/src/components/ui/toggle.tsx +0 -47
  127. package/src/components/ui/tooltip.tsx +0 -61
  128. package/src/components/vast-ai-live-pricing.tsx +0 -176
  129. package/src/hooks/use-mobile.ts +0 -19
  130. package/src/hooks/use-toast.ts +0 -194
  131. package/src/lib/benchmark-parser-sglang.ts +0 -150
  132. package/src/lib/benchmark-parser-tokcalc.ts +0 -247
  133. package/src/lib/benchmark-parser-trtllm.ts +0 -152
  134. package/src/lib/benchmark-parser-vllm.ts +0 -198
  135. package/src/lib/benchmark-schema.ts +0 -263
  136. package/src/lib/db.ts +0 -13
  137. package/src/lib/engine-presets.ts +0 -183
  138. package/src/lib/price-schema.ts +0 -141
  139. package/src/lib/token-calc.ts +0 -808
  140. package/src/lib/track.ts +0 -31
  141. package/src/lib/url-state.ts +0 -256
  142. package/src/lib/utils.ts +0 -6
  143. package/tailwind.config.ts +0 -64
  144. package/tests/database-runtime-build.sh +0 -75
  145. package/tests/python-runtime-build.sh +0 -64
  146. package/tests/python-runtime-container.sh +0 -31
  147. package/tool-results/bash_1789888171144_2c5381860539.txt +0 -161
  148. package/tool-results/bash_1789888175925_49c53ba3c61b.txt +0 -191
  149. package/tool-results/bash_1789888181202_49c53ba3c61b.txt +0 -191
  150. package/tool-results/bash_1789888195219_4a86a5c91411.txt +0 -200
  151. package/tool-results/bash_1789888203128_6cca13c71b47.txt +0 -199
  152. package/tool-results/bash_1789929256963_2a52aff0d0a8.txt +0 -160
  153. package/tool-results/read_1789888151021_69f58eec6a5b.txt +0 -653
  154. package/tool-results/read_1789888153837_1d3a8bfc2a94.txt +0 -653
  155. package/tool-results/read_1789888163087_ccc406d47505.txt +0 -122
  156. package/tool-results/read_1789888167347_67d1d7c9830a.txt +0 -122
  157. package/tool-results/read_1789929252529_d90e8f383a25.txt +0 -285
  158. package/tsconfig.json +0 -42
  159. package/upload/Pasted Content_1789887800864.txt +0 -652
  160. package/upload/Pasted Content_1789887909561.txt +0 -652
  161. package/upload/Pasted Content_1789887918428.txt +0 -652
  162. package/upload/Pasted Content_1789887959420.txt +0 -652
  163. package/upload/Pasted Content_1789888020485.txt +0 -652
  164. package/upload/Pasted Content_1789888058079.txt +0 -652
  165. package/upload/Pasted Content_1789888885033.txt +0 -686
  166. package/upload/Pasted Content_1789928912741.txt +0 -285
  167. package/upload/Pasted Content_1789928938402.txt +0 -285
  168. package/upload/Pasted Content_1789929160389.txt +0 -285
  169. package/upload/Pasted Content_1789929176660.txt +0 -285
  170. package/upload/issue_vision.json +0 -28
  171. package/upload/pasted_image_1789883175209.png +0 -0
  172. package/upload/pasted_image_1789899056690.png +0 -0
  173. package/upload/pasted_image_1789900371483.png +0 -0
  174. package/upload/pasted_image_1789900472823.png +0 -0
  175. package/upload/pasted_image_1789900490374.png +0 -0
  176. package/upload/pasted_image_1789900585552.png +0 -0
  177. package/upload/pasted_image_1789900606519.png +0 -0
  178. package/upload/pasted_image_1789901598705.png +0 -0
  179. package/upload/pasted_image_1789901613545.png +0 -0
  180. package/upload/pasted_image_1789978382674.png +0 -0
  181. package/upload/pasted_image_1789978392749.png +0 -0
  182. package/upload/pasted_image_1789978474879.png +0 -0
  183. package/upload/pasted_image_1789978523652.png +0 -0
  184. package/upload/pasted_image_1789984219089.png +0 -0
  185. package/upload/pasted_image_1789984491896.png +0 -0
  186. package/upload/pasted_image_1789985017950.png +0 -0
  187. package/upload/pasted_image_1789985036765.png +0 -0
  188. package/upload/pasted_image_1789985049848.png +0 -0
  189. package/upload/pasted_image_1790002427833.png +0 -0
  190. package/upload/pasted_image_1790002659944.png +0 -0
  191. package/upload/pasted_image_1790037038476.png +0 -0
  192. package/upload/screenshot_analysis.json +0 -28
  193. 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)