claudmax 1.0.16 → 2.0.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 (124) hide show
  1. package/.claude/settings.local.json +7 -0
  2. package/.env.example +24 -0
  3. package/.github/workflows/publish.yml +31 -0
  4. package/README.md +178 -0
  5. package/claudmax-1.0.16.tgz +0 -0
  6. package/claudmax-mcp-1.0.2.tgz +0 -0
  7. package/help +0 -0
  8. package/help-wal +0 -0
  9. package/next-env.d.ts +6 -0
  10. package/next.config.mjs +43 -0
  11. package/package.json +55 -27
  12. package/{bin → packages/cli/bin}/claudmax.js +2 -0
  13. package/packages/cli/claudmax-1.0.16.tgz +0 -0
  14. package/packages/cli/claudmax-1.0.17.tgz +0 -0
  15. package/{index.js → packages/cli/index.js} +1 -1
  16. package/packages/cli/package.json +33 -0
  17. package/packages/mcp/claudmax-mcp-1.0.0.tgz +0 -0
  18. package/packages/mcp/claudmax-mcp-1.0.1.tgz +0 -0
  19. package/packages/mcp/claudmax-mcp-1.0.2.tgz +0 -0
  20. package/packages/mcp/claudmax-mcp-1.0.3.tgz +0 -0
  21. package/packages/mcp/index.js +129 -0
  22. package/packages/mcp/package-lock.json +1146 -0
  23. package/packages/mcp/package.json +32 -0
  24. package/postcss.config.mjs +6 -0
  25. package/prisma/schema.prisma +130 -0
  26. package/prisma/seed.ts +27 -0
  27. package/public/favicon.svg +10 -0
  28. package/public/robots.txt +10 -0
  29. package/run_build.sh +4 -0
  30. package/scripts/migrate-plans.js +98 -0
  31. package/scripts/seed-blog.ts +1014 -0
  32. package/src/app/admin/dashboard/AdminDashboardClient.tsx +1546 -0
  33. package/src/app/admin/dashboard/page.tsx +13 -0
  34. package/src/app/admin/page.tsx +132 -0
  35. package/src/app/api/admin/auth/me/route.ts +34 -0
  36. package/src/app/api/admin/health/route.ts +110 -0
  37. package/src/app/api/admin/keys/[id]/route.ts +116 -0
  38. package/src/app/api/admin/keys/route.ts +192 -0
  39. package/src/app/api/admin/keys-list/route.ts +81 -0
  40. package/src/app/api/admin/login/route.ts +72 -0
  41. package/src/app/api/admin/logout/route.ts +8 -0
  42. package/src/app/api/admin/migrate/route.ts +133 -0
  43. package/src/app/api/admin/plans/[id]/route.ts +65 -0
  44. package/src/app/api/admin/plans/route.ts +66 -0
  45. package/src/app/api/admin/posts/[id]/route.ts +81 -0
  46. package/src/app/api/admin/posts/route.ts +83 -0
  47. package/src/app/api/admin/seed/route.ts +145 -0
  48. package/src/app/api/admin/settings/route.ts +44 -0
  49. package/src/app/api/admin/stats/route.ts +74 -0
  50. package/src/app/api/admin/users/[id]/route.ts +166 -0
  51. package/src/app/api/admin/users/plans/route.ts +45 -0
  52. package/src/app/api/admin/users/route.ts +202 -0
  53. package/src/app/api/blog/[slug]/route.ts +22 -0
  54. package/src/app/api/blog/route.ts +40 -0
  55. package/src/app/api/cron/daily-status/route.ts +208 -0
  56. package/src/app/api/support/chat/route.ts +55 -0
  57. package/src/app/api/support/chat/session/route.ts +62 -0
  58. package/src/app/api/support/chat/stream/route.ts +44 -0
  59. package/src/app/api/support/email/route.ts +63 -0
  60. package/src/app/api/tools/understand_image/route.ts +113 -0
  61. package/src/app/api/tools/upload/route.ts +179 -0
  62. package/src/app/api/tools/web_search/route.ts +99 -0
  63. package/src/app/api/v1/audio/route.ts +67 -0
  64. package/src/app/api/v1/audio/speech/route.ts +73 -0
  65. package/src/app/api/v1/chat/completions/route.ts +3 -0
  66. package/src/app/api/v1/chat/route.ts +1079 -0
  67. package/src/app/api/v1/images/generations/route.ts +93 -0
  68. package/src/app/api/v1/info/route.ts +30 -0
  69. package/src/app/api/v1/key-status/route.ts +109 -0
  70. package/src/app/api/v1/key-status/stream/route.ts +135 -0
  71. package/src/app/api/v1/messages/count_tokens/route.ts +22 -0
  72. package/src/app/api/v1/messages/route.ts +807 -0
  73. package/src/app/api/v1/models/route.ts +14 -0
  74. package/src/app/api/v1/route.ts +18 -0
  75. package/src/app/blog/BlogClient.tsx +193 -0
  76. package/src/app/blog/[slug]/page.tsx +117 -0
  77. package/src/app/blog/page.tsx +20 -0
  78. package/src/app/check-usage/CheckUsageClient.tsx +186 -0
  79. package/src/app/check-usage/layout.tsx +11 -0
  80. package/src/app/check-usage/page.tsx +15 -0
  81. package/src/app/docs/layout.tsx +16 -0
  82. package/src/app/docs/page.tsx +1055 -0
  83. package/src/app/faq/FAQClient.tsx +227 -0
  84. package/src/app/faq/page.tsx +21 -0
  85. package/src/app/globals.css +75 -0
  86. package/src/app/layout.tsx +80 -0
  87. package/src/app/page.tsx +256 -0
  88. package/src/app/reseller/ResellerClient.tsx +435 -0
  89. package/src/app/reseller/page.tsx +15 -0
  90. package/src/app/setup.ps1/route.ts +79 -0
  91. package/src/app/setup.sh/route.ts +113 -0
  92. package/src/app/sitemap.ts +50 -0
  93. package/src/app/status/StatusClient.tsx +103 -0
  94. package/src/app/status/layout.tsx +11 -0
  95. package/src/app/status/page.tsx +15 -0
  96. package/src/app/support/SupportClient.tsx +411 -0
  97. package/src/app/support/page.tsx +25 -0
  98. package/src/app/v1/chat/completions/route.ts +3 -0
  99. package/src/app/v1/chat/route.ts +4 -0
  100. package/src/app/v1/messages/route.ts +3 -0
  101. package/src/components/Footer.tsx +120 -0
  102. package/src/components/Header.tsx +131 -0
  103. package/src/components/landing/features.tsx +99 -0
  104. package/src/components/ui/badge.tsx +32 -0
  105. package/src/components/ui/button.tsx +46 -0
  106. package/src/components/ui/card.tsx +50 -0
  107. package/src/components/ui/dialog.tsx +97 -0
  108. package/src/components/ui/dropdown-menu.tsx +156 -0
  109. package/src/components/ui/input.tsx +21 -0
  110. package/src/components/ui/label.tsx +15 -0
  111. package/src/components/ui/separator.tsx +22 -0
  112. package/src/components/ui/switch.tsx +27 -0
  113. package/src/components/ui/tabs.tsx +51 -0
  114. package/src/components/ui/toast.tsx +103 -0
  115. package/src/lib/auth.ts +45 -0
  116. package/src/lib/prisma.ts +20 -0
  117. package/src/lib/providers.ts +158 -0
  118. package/src/lib/security.ts +165 -0
  119. package/src/lib/utils.ts +14 -0
  120. package/src/middleware.ts +30 -0
  121. package/tailwind.config.ts +53 -0
  122. package/tsconfig.json +41 -0
  123. package/tsconfig.tsbuildinfo +1 -0
  124. package/vercel.json +8 -0
@@ -0,0 +1,7 @@
1
+ {
2
+ "permissions": {
3
+ "allow": [
4
+ "WebFetch(domain:claudmax.pro)"
5
+ ]
6
+ }
7
+ }
package/.env.example ADDED
@@ -0,0 +1,24 @@
1
+ # Environment Variables for ClaudeMax
2
+
3
+ # NextAuth
4
+ NEXTAUTH_URL=https://your-domain.com
5
+ NEXTAUTH_SECRET=generate-with-openssl-rand-base64-32
6
+
7
+ # Database (use Turso SQLite or Neon Postgres)
8
+ DATABASE_URL="libsql://your-db.turso.io?authToken=your-token"
9
+ # For local dev: DATABASE_URL="file:./dev.db"
10
+
11
+ # OpenRouter API Key (get from https://openrouter.ai/keys)
12
+ OPENROUTER_API_KEY=sk-or-v1-your-openrouter-api-key
13
+
14
+ # LiteRouter API Key — primary backend (get from https://literouter.com)
15
+ # Unlimited free requests/day on 5 free models (gemini-free, gpt-free, deepseek-free, glm-free, kimi-k2-thinking-free)
16
+ # Note: 7.5s cooldown between requests, 1 concurrent request per key
17
+ LITEROUTER_API_KEY=your-literouter-api-key
18
+
19
+ # OpenRouter Site URL & Referer
20
+ OPENROUTER_SITE_URL=https://your-domain.com
21
+ OPENROUTER_SITE_NAME=ClaudMax
22
+
23
+ # App Base URL
24
+ NEXT_PUBLIC_APP_URL=https://your-domain.com
@@ -0,0 +1,31 @@
1
+ name: Publish npm Package
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+ paths:
8
+ - 'packages/cli/**'
9
+ workflow_dispatch:
10
+
11
+ jobs:
12
+ publish:
13
+ runs-on: ubuntu-latest
14
+ permissions:
15
+ contents: read
16
+ id-token: write
17
+ steps:
18
+ - uses: actions/checkout@v4
19
+
20
+ - uses: actions/setup-node@v4
21
+ with:
22
+ node-version: '20'
23
+ registry-url: 'https://registry.npmjs.org'
24
+
25
+ - name: Publish CLI package
26
+ working-directory: packages/cli
27
+ run: |
28
+ npm ci
29
+ npm publish --access public --provenance
30
+ env:
31
+ NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
package/README.md ADDED
@@ -0,0 +1,178 @@
1
+ # ClaudeMax
2
+
3
+ > OpenAI-compatible API proxy powered by OpenRouter. Use Claude Code models in any IDE.
4
+
5
+ ## Features
6
+
7
+ - **OpenAI-Compatible API** — Drop-in replacement for OpenAI API endpoints
8
+ - **Claude Models** — Access Claude 3.5 Haiku, Sonnet, and Opus via OpenRouter
9
+ - **API Key Management** — Generate, revoke, and track API keys from your dashboard
10
+ - **Usage Analytics** — Real-time request tracking, token counts, and latency metrics
11
+ - **Rate Limiting** — Per-user, per-tier rate limits out of the box
12
+ - **Multi-Provider** — Claude, GPT-4o, Gemini Pro, DeepSeek, and 50+ models
13
+ - **Self-Hosted** — Deploy on Vercel, Railway, Render, or any Node.js platform
14
+
15
+ ## Tech Stack
16
+
17
+ - **Framework:** Next.js 14 (App Router)
18
+ - **Styling:** Tailwind CSS + shadcn/ui
19
+ - **Database:** SQLite (dev) / Turso (prod)
20
+ - **ORM:** Prisma
21
+ - **Auth:** NextAuth.js v4
22
+ - **Proxy:** OpenRouter API
23
+
24
+ ## Getting Started
25
+
26
+ ### Prerequisites
27
+
28
+ - Node.js 18+
29
+ - npm or pnpm
30
+ - OpenRouter API key ([get one here](https://openrouter.ai/keys))
31
+
32
+ ### Installation
33
+
34
+ ```bash
35
+ # Clone the repository
36
+ git clone https://github.com/yourusername/claudemax.git
37
+ cd claudemax
38
+
39
+ # Install dependencies
40
+ npm install
41
+
42
+ # Set up environment variables
43
+ cp .env.example .env.local
44
+ # Edit .env.local with your values
45
+
46
+ # Initialize database
47
+ npm run db:push
48
+ npm run db:generate
49
+
50
+ # Start development server
51
+ npm run dev
52
+ ```
53
+
54
+ Visit [http://localhost:3000](http://localhost:3000)
55
+
56
+ ### Environment Variables
57
+
58
+ | Variable | Description |
59
+ |---|---|
60
+ | `NEXTAUTH_URL` | Your app URL (e.g. http://localhost:3000) |
61
+ | `NEXTAUTH_SECRET` | Random secret for NextAuth (generate with `openssl rand -base64 32`) |
62
+ | `DATABASE_URL` | SQLite: `file:./dev.db` / Turso: `libsql://your-db.turso.io?authToken=...` |
63
+ | `OPENROUTER_API_KEY` | Your OpenRouter API key |
64
+ | `OPENROUTER_SITE_URL` | Your site URL for OpenRouter referer |
65
+ | `OPENROUTER_SITE_NAME` | Your site name |
66
+
67
+ ## Usage
68
+
69
+ ### 1. Register & Get API Key
70
+
71
+ Sign up at `/register`, then go to Dashboard → API Keys → Create Key.
72
+
73
+ ### 2. Use in Your App
74
+
75
+ ```bash
76
+ # cURL
77
+ curl -X POST https://api.yourdomain.com/v1/chat/completions \
78
+ -H "Authorization: Bearer cmx_your_api_key" \
79
+ -H "Content-Type: application/json" \
80
+ -d '{
81
+ "model": "anthropic/claude-3.5-sonnet",
82
+ "messages": [{"role": "user", "content": "Hello!"}]
83
+ }'
84
+ ```
85
+
86
+ ```python
87
+ # Python
88
+ from openai import OpenAI
89
+
90
+ client = OpenAI(
91
+ base_url="https://api.yourdomain.com/v1",
92
+ api_key="cmx_your_api_key",
93
+ )
94
+
95
+ chat = client.chat.completions.create(
96
+ model="anthropic/claude-3.5-sonnet",
97
+ messages=[{"role": "user", "content": "Hello!"}],
98
+ )
99
+ ```
100
+
101
+ ### 3. Works with Popular Tools
102
+
103
+ - **Cursor** — Settings → Models → Add API Key → Set base URL
104
+ - **Cline** — Settings → API Configuration → Custom provider
105
+ - **OpenClaw** — Settings → API Provider → OpenAI compatible
106
+ - **Continue.dev** — Config → Add model with custom base URL
107
+ - **Aider** — `aider --openai-api-base https://api.yourdomain.com/v1 --openai-api-key cmx_...`
108
+
109
+ ## Pricing Tiers
110
+
111
+ | Tier | Price | Requests/Day | Tokens/Month |
112
+ |---|---|---|---|
113
+ | Free | $0 | 100 | 100K |
114
+ | Starter | $9/mo | 1,000 | 500K |
115
+ | Pro | $29/mo | 5,000 | 2M |
116
+ | Max | $79/mo | 20,000 | 10M |
117
+
118
+ ## Deployment
119
+
120
+ ### Vercel (Recommended)
121
+
122
+ ```bash
123
+ npm i -g vercel
124
+ vercel
125
+ ```
126
+
127
+ Set environment variables in Vercel dashboard. Use **Turso** or **Neon** for the database.
128
+
129
+ ### Railway
130
+
131
+ ```bash
132
+ railway init
133
+ railway up
134
+ ```
135
+
136
+ ### Docker
137
+
138
+ ```dockerfile
139
+ FROM node:18-alpine
140
+ WORKDIR /app
141
+ COPY package*.json ./
142
+ RUN npm ci
143
+ COPY . .
144
+ RUN npx prisma generate
145
+ RUN npx prisma db push
146
+ EXPOSE 3000
147
+ CMD ["npm", "start"]
148
+ ```
149
+
150
+ ## Project Structure
151
+
152
+ ```
153
+ src/
154
+ ├── app/
155
+ │ ├── api/
156
+ │ │ ├── auth/ # NextAuth endpoints
157
+ │ │ ├── v1/
158
+ │ │ │ ├── chat/ # Proxy endpoint (core)
159
+ │ │ │ ├── models/ # Available models list
160
+ │ │ │ └── route.ts # Health check
161
+ │ │ ├── keys/ # API key CRUD
162
+ │ │ └── usage/ # Usage logs
163
+ │ ├── dashboard/ # Protected dashboard pages
164
+ │ ├── login/ # Auth pages
165
+ │ └── page.tsx # Landing page
166
+ ├── components/
167
+ │ ├── landing/ # Landing page sections
168
+ │ └── ui/ # shadcn-style components
169
+ └── lib/
170
+ ├── auth.ts # NextAuth config
171
+ ├── prisma.ts # Prisma client
172
+ ├── rate-limiter.ts # In-memory rate limiting
173
+ └── utils.ts # Helpers, pricing, constants
174
+ ```
175
+
176
+ ## License
177
+
178
+ MIT
Binary file
Binary file
package/help ADDED
File without changes
package/help-wal ADDED
File without changes
package/next-env.d.ts ADDED
@@ -0,0 +1,6 @@
1
+ /// <reference types="next" />
2
+ /// <reference types="next/image-types/global" />
3
+ import "./.next/types/routes.d.ts";
4
+
5
+ // NOTE: This file should not be edited
6
+ // see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
@@ -0,0 +1,43 @@
1
+ /** @type {import('next').NextConfig} */
2
+ const nextConfig = {
3
+ images: {
4
+ remotePatterns: [
5
+ { protocol: 'https', hostname: 'avatars.githubusercontent.com' },
6
+ { protocol: 'https', hostname: 'lh3.googleusercontent.com' },
7
+ ],
8
+ },
9
+ serverExternalPackages: ['@prisma/client', 'bcryptjs'],
10
+ async headers() {
11
+ return [
12
+ {
13
+ source: '/api/:path*',
14
+ headers: [
15
+ { key: 'X-Content-Type-Options', value: 'nosniff' },
16
+ { key: 'X-Frame-Options', value: 'DENY' },
17
+ { key: 'X-XSS-Protection', value: '1; mode=block' },
18
+ { key: 'Content-Security-Policy', value: "default-src 'none'; frame-ancestors 'none';" },
19
+ { key: 'Server', value: 'Claude-API' },
20
+ { key: 'X-Powered-By', value: '' },
21
+ ],
22
+ },
23
+ ];
24
+ },
25
+ async rewrites() {
26
+ return [
27
+ // For api.claudmax.pro — rewrite / to /api/v1 (returns JSON 404)
28
+ {
29
+ source: '/',
30
+ has: [{ type: 'host', value: '^(www\\.)?api\\.claudmax\\.pro$' }],
31
+ destination: '/api/v1',
32
+ },
33
+ // For api.claudmax.pro — rewrite /v1/* to /api/v1/*
34
+ {
35
+ source: '/v1/:path*',
36
+ has: [{ type: 'host', value: '^(www\\.)?api\\.claudmax\\.pro$' }],
37
+ destination: '/api/v1/:path*',
38
+ },
39
+ ];
40
+ },
41
+ };
42
+
43
+ export default nextConfig;
package/package.json CHANGED
@@ -1,33 +1,61 @@
1
1
  {
2
2
  "name": "claudmax",
3
- "version": "1.0.16",
4
- "description": "ClaudMax CLI — Configure Claude Code, Cursor, Windsurf, Cline, and Roo Code to use ClaudMax API gateway with one command",
5
- "main": "index.js",
6
- "bin": {
7
- "claudmax": "./index.js"
8
- },
3
+ "version": "2.0.0",
9
4
  "scripts": {
10
- "start": "node ./index.js"
5
+ "dev": "next dev",
6
+ "build": "next build",
7
+ "start": "next start",
8
+ "lint": "next lint",
9
+ "db:push": "prisma db push",
10
+ "db:generate": "prisma generate",
11
+ "db:studio": "prisma studio",
12
+ "db:seed": "tsx prisma/seed.ts",
13
+ "postinstall": "prisma generate"
11
14
  },
12
- "keywords": [
13
- "claudmax",
14
- "claude",
15
- "claude-code",
16
- "anthropic",
17
- "ai",
18
- "api",
19
- "proxy",
20
- "gateway",
21
- "cursor",
22
- "windsurf",
23
- "cline",
24
- "mcp",
25
- "setup",
26
- "openrouter"
27
- ],
28
- "license": "MIT",
29
- "engines": {
30
- "node": ">=16.0.0"
15
+ "dependencies": {
16
+ "@auth/prisma-adapter": "^2.7.2",
17
+ "@libsql/client": "^0.17.2",
18
+ "@modelcontextprotocol/sdk": "^1.29.0",
19
+ "@prisma/adapter-libsql": "^7.7.0",
20
+ "@prisma/client": "^6.19.3",
21
+ "@radix-ui/react-dialog": "^1.1.2",
22
+ "@radix-ui/react-dropdown-menu": "^2.1.2",
23
+ "@radix-ui/react-label": "^2.1.0",
24
+ "@radix-ui/react-progress": "^1.1.0",
25
+ "@radix-ui/react-slot": "^1.1.0",
26
+ "@radix-ui/react-switch": "^1.1.1",
27
+ "@radix-ui/react-tabs": "^1.1.1",
28
+ "@radix-ui/react-toast": "^1.2.2",
29
+ "bcryptjs": "^2.4.3",
30
+ "class-variance-authority": "^0.7.0",
31
+ "clsx": "^2.1.1",
32
+ "jsonwebtoken": "^9.0.3",
33
+ "lucide-react": "^0.460.0",
34
+ "next": "^16.2.2",
35
+ "next-auth": "^4.24.10",
36
+ "react": "^18.3.1",
37
+ "react-dom": "^18.3.1",
38
+ "resend": "^6.10.0",
39
+ "tailwind-merge": "^2.5.4",
40
+ "tailwindcss-animate": "^1.0.7",
41
+ "tsx": "^4.21.0",
42
+ "uuid": "^11.0.3",
43
+ "zod": "^3.23.8"
31
44
  },
32
- "preferGlobal": true
45
+ "devDependencies": {
46
+ "@types/bcryptjs": "^2.4.6",
47
+ "@types/better-sqlite3": "^7.6.13",
48
+ "@types/jsonwebtoken": "^9.0.10",
49
+ "@types/node": "^22.9.0",
50
+ "@types/react": "^18.3.12",
51
+ "@types/react-dom": "^18.3.1",
52
+ "@types/uuid": "^10.0.0",
53
+ "autoprefixer": "^10.4.20",
54
+ "eslint": "^8.57.1",
55
+ "eslint-config-next": "14.2.18",
56
+ "postcss": "^8.4.47",
57
+ "prisma": "^6.19.3",
58
+ "tailwindcss": "^3.4.14",
59
+ "typescript": "^5.6.3"
60
+ }
33
61
  }
@@ -94,6 +94,8 @@ async function cmdConfigure() {
94
94
  printBanner();
95
95
  console.log(`${BOLD}Configure your ClaudMax API key${RESET}`);
96
96
  console.log('');
97
+ console.log(`${CYAN}Get Your API Key: https://www.claudmax.pro/support${RESET}`);
98
+ console.log('');
97
99
 
98
100
  const config = getConfig();
99
101
  if (config?.apiKey) {
Binary file
Binary file
@@ -80,7 +80,7 @@ function verifyConnection(apiKey) {
80
80
  method: 'POST',
81
81
  headers: {
82
82
  'Content-Type': 'application/json',
83
- 'User-Agent': 'ClaudMax-CLI/1.0.15',
83
+ 'User-Agent': 'ClaudMax-CLI/2.0.0',
84
84
  },
85
85
  timeout: 15000,
86
86
  };
@@ -0,0 +1,33 @@
1
+ {
2
+ "name": "claudmax",
3
+ "version": "2.0.0",
4
+ "description": "ClaudMax CLI — Configure Claude Code, Cursor, Windsurf, Cline, and Roo Code to use ClaudMax API gateway with one command",
5
+ "main": "index.js",
6
+ "bin": {
7
+ "claudmax": "./index.js"
8
+ },
9
+ "scripts": {
10
+ "start": "node ./index.js"
11
+ },
12
+ "keywords": [
13
+ "claudmax",
14
+ "claude",
15
+ "claude-code",
16
+ "anthropic",
17
+ "ai",
18
+ "api",
19
+ "proxy",
20
+ "gateway",
21
+ "cursor",
22
+ "windsurf",
23
+ "cline",
24
+ "mcp",
25
+ "setup",
26
+ "openrouter"
27
+ ],
28
+ "license": "MIT",
29
+ "engines": {
30
+ "node": ">=16.0.0"
31
+ },
32
+ "preferGlobal": true
33
+ }
@@ -0,0 +1,129 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * ClaudMax MCP Server
5
+ * Exposes Claude AI tools via the Model Context Protocol.
6
+ */
7
+
8
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
9
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
10
+ import { z } from 'zod';
11
+
12
+ // ── Config ──────────────────────────────────────────────────────────────────
13
+ const API_KEY = process.env.CLAUDMAX_API_KEY || process.env.ANTHROPIC_API_KEY;
14
+ const API_BASE = (process.env.CLAUDMAX_URL || process.env.ANTHROPIC_BASE_URL || 'https://api.claudmax.pro').replace(/\/+$/, '');
15
+ const TIMEOUT_MS = 30000;
16
+
17
+ // ── Helpers ──────────────────────────────────────────────────────────────────
18
+ async function apiCall(path, body, timeout = TIMEOUT_MS) {
19
+ if (!API_KEY) {
20
+ throw new Error('CLAUDMAX_API_KEY or ANTHROPIC_API_KEY is not set');
21
+ }
22
+ const controller = new AbortController();
23
+ const timer = setTimeout(() => controller.abort(), timeout);
24
+ try {
25
+ const res = await fetch(`${API_BASE}${path}`, {
26
+ method: 'POST',
27
+ headers: {
28
+ 'Content-Type': 'application/json',
29
+ 'x-api-key': API_KEY,
30
+ },
31
+ body: JSON.stringify(body),
32
+ signal: controller.signal,
33
+ });
34
+ if (!res.ok) {
35
+ const err = await res.json().catch(() => ({ error: { message: `HTTP ${res.status}` } }));
36
+ throw new Error(err.error?.message || err.error || `API error: ${res.status}`);
37
+ }
38
+ return await res.json();
39
+ } finally {
40
+ clearTimeout(timer);
41
+ }
42
+ }
43
+
44
+ // ── MCP Server ───────────────────────────────────────────────────────────────
45
+ const server = new McpServer(
46
+ { name: 'ClaudMax', version: '2.0.0' },
47
+ { capabilities: { tools: {} } }
48
+ );
49
+
50
+ // ── Tools ─────────────────────────────────────────────────────────────────────
51
+
52
+ // web_search
53
+ server.registerTool('web_search', {
54
+ title: 'Web Search',
55
+ description: 'Search the web using ClaudMax API. Great for looking up current information, facts, news, and research.',
56
+ inputSchema: z.object({
57
+ query: z.string().describe('The search query'),
58
+ model: z.string().optional().describe('Model to use (optional)'),
59
+ }),
60
+ }, async ({ query, model }) => {
61
+ try {
62
+ const result = await apiCall('/api/tools/web_search', { query, model });
63
+ const items = result.results || result.organic || [];
64
+ const text = items.map((r) => `## ${r.title}\n${r.snippet || r.summary || ''}\n${r.link || r.url || ''}`).join('\n\n');
65
+ return { content: [{ type: 'text', text: text || 'No results.' }] };
66
+ } catch (err) {
67
+ return { content: [{ type: 'text', text: `Search failed: ${err.message}` }], isError: true };
68
+ }
69
+ });
70
+
71
+ // understand_image
72
+ server.registerTool('understand_image', {
73
+ title: 'Understand Image',
74
+ description: 'Analyze an image to understand its contents, describe objects, text, charts, or any visual information.',
75
+ inputSchema: z.object({
76
+ image_url: z.string().describe('URL or base64 data URL of the image'),
77
+ prompt: z.string().optional().describe('Question about the image'),
78
+ }),
79
+ }, async ({ image_url, prompt }) => {
80
+ try {
81
+ const result = await apiCall('/api/tools/understand_image', {
82
+ image_url,
83
+ prompt: prompt || 'Describe this image.',
84
+ });
85
+ return { content: [{ type: 'text', text: result.description || result.content || 'Unable to analyze.' }] };
86
+ } catch (err) {
87
+ return { content: [{ type: 'text', text: `Image analysis failed: ${err.message}` }], isError: true };
88
+ }
89
+ });
90
+
91
+ // upload_file
92
+ server.registerTool('upload_file', {
93
+ title: 'Upload File',
94
+ description: 'Upload and process files. Images are analyzed, text files are read. Supports PNG, JPEG, GIF, WebP, SVG, PDF, TXT, MD, JSON, CSV.',
95
+ inputSchema: z.object({
96
+ name: z.string().describe('Filename with extension (e.g. photo.png)'),
97
+ mime_type: z.string().describe('MIME type (e.g. image/png)'),
98
+ data: z.string().describe('Base64-encoded file contents'),
99
+ prompt: z.string().optional().describe('What to do with the file'),
100
+ }),
101
+ }, async ({ name, mime_type, data, prompt }) => {
102
+ try {
103
+ const result = await apiCall('/api/tools/upload', {
104
+ files: [{ name, mime_type, data }],
105
+ prompt: prompt || 'Process this file.',
106
+ });
107
+ const files = result.files || [];
108
+ const outputs = files.map((f) => {
109
+ if (f.error) return `ERROR ${f.name}: ${f.error}`;
110
+ if (f.type === 'image') return `IMAGE ${f.name}: ${f.description || f.content}`;
111
+ if (f.type === 'text') return `TEXT ${f.name}:\n${f.content}`;
112
+ return `FILE ${f.name}: processed`;
113
+ });
114
+ return { content: [{ type: 'text', text: outputs.join('\n') }] };
115
+ } catch (err) {
116
+ return { content: [{ type: 'text', text: `Upload failed: ${err.message}` }], isError: true };
117
+ }
118
+ });
119
+
120
+ // ── Start ─────────────────────────────────────────────────────────────────────
121
+ async function main() {
122
+ const transport = new StdioServerTransport();
123
+ await server.connect(transport);
124
+ }
125
+
126
+ main().catch((err) => {
127
+ console.error('ClaudMax MCP error:', err.message);
128
+ process.exit(1);
129
+ });