@upstash/mcp-server 0.0.7 โ†’ 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.
package/README.md CHANGED
@@ -4,41 +4,109 @@
4
4
 
5
5
  Model Context Protocol (MCP) is a [new, standardized protocol](https://modelcontextprotocol.io/introduction) for managing context between large language models (LLMs) and external systems. In this repository, we provide an installer as well as an MCP Server for [Upstash Developer API's](https://upstash.com/docs/devops/developer-api).
6
6
 
7
- This lets you use Claude Desktop, or any MCP Client, to use natural language to accomplish things on your Upstash account, e.g.:
7
+ This allows you to use any MCP Client to interact with your Upstash account using natural language, e.g.:
8
8
 
9
9
  - "Create a new Redis database in us-east-1"
10
- - "List all databases"
11
- - "See keys starting with "user:" in users-db"
10
+ - "List my databases"
11
+ - "List keys starting with "user:" in users-db"
12
12
  - "Create a backup"
13
- - "Give me the spikes in throughput for the last 7 days"
13
+ - "Give me the spikes in throughput during the last 7 days"
14
14
 
15
15
  # Usage
16
16
 
17
17
  ## Requirements
18
18
 
19
19
  - Node.js >= v18.0.0
20
- - Claude Desktop
21
20
  - [Upstash API key](https://upstash.com/docs/devops/developer-api) - You can create one from [here](https://console.upstash.com/account/api).
22
21
 
23
22
  ## How to use locally
24
23
 
25
- ### Installing via Smithery
24
+ ### Installing for Claude Desktop
26
25
 
27
- To install Upstash for Claude Desktop automatically via [Smithery](https://smithery.ai/server/@upstash/mcp-server):
26
+ To install Upstash MCP Server for Claude Desktop automatically via [Smithery](https://smithery.ai/server/@upstash/mcp-server) run the following command:
28
27
 
29
28
  ```bash
30
- npx -y @smithery/cli install @upstash/mcp-server --client claude
29
+ npx -y @smithery/cli@latest install @upstash/mcp-server --client claude
31
30
  ```
32
31
 
33
- ### Installing manually
32
+ <details>
33
+ <summary>Install without Smithery</summary>
34
+
35
+ ```bash
36
+ npx @upstash/mcp-server init <UPSTASH_EMAIL> <UPSTASH_API_KEY>
37
+ ```
34
38
 
35
- 1. Run `npx @upstash/mcp-server init <UPSTASH_EMAIL> <UPSTASH_API_KEY>`
36
- 2. Restart Claude Desktop
37
- 3. You should now be able to use Upstash commands in Claude Desktop
39
+ This will edit your MCP config file and add an entry for Upstash.
38
40
 
39
- See the [troubleshooting guide](https://modelcontextprotocol.io/quickstart#troubleshooting) in the MCP documentation. You can also reach out to us at [Discord](https://discord.com/invite/w9SenAtbme).
41
+ </details>
42
+
43
+ ### Installing for Cursor
44
+
45
+ To install Upstash MCP Server for Cursor automatically via [Smithery](https://smithery.ai/server/@upstash/mcp-server) run the following command:
46
+
47
+ ```bash
48
+ npx -y @smithery/cli@latest install @upstash/mcp-server --client cursor
49
+ ```
50
+
51
+ <details>
52
+ <summary>Install without Smithery</summary>
53
+
54
+ Add the following command to the MCP config in Cursor. For more info, check the [Cursor MCP docs](https://docs.cursor.com/context/model-context-protocol#configuring-mcp-servers).
55
+
56
+ ```bash
57
+ npx -y @upstash/mcp-server run <UPSTASH_EMAIL> <UPSTASH_API_KEY>
58
+ ```
59
+
60
+ </details>
61
+
62
+ ### Installing for Windsurf
40
63
 
41
- > NOTE: If you are using a node version manager like nvm or fnm, please check [this issue](https://github.com/modelcontextprotocol/servers/issues/64#issuecomment-2530337743). You should change the `node` command in the MCP config to the absolute path of the node binary.
64
+ To install Upstash MCP Server for Windsurf automatically via [Smithery](https://smithery.ai/server/@upstash/mcp-server) run the following command:
65
+
66
+ ```bash
67
+ npx -y @smithery/cli@latest install @upstash/mcp-server --client windsurf
68
+ ```
69
+
70
+ <details>
71
+ <summary>Install without Smithery</summary>
72
+
73
+ Add the following command to the MCP config in Windsurf. For more info, check out the [Windsurf MCP docs](https://docs.windsurf.com/windsurf/mcp#mcp-config-json).
74
+
75
+ ```bash
76
+ npx -y @upstash/mcp-server run <UPSTASH_EMAIL> <UPSTASH_API_KEY>
77
+ ```
78
+
79
+ </details>
80
+
81
+ ### Running with Docker
82
+
83
+ You can also use the provided Docker image to run the server.
84
+
85
+ ```bash
86
+ docker build -t upstash-mcp .
87
+
88
+ # Run the stdio server, add this command to you MCP config
89
+ docker run --rm -i \
90
+ -e UPSTASH_EMAIL=<UPSTASH_EMAIL> \
91
+ -e UPSTASH_API_KEY=<UPSTASH_API_KEY> \
92
+ upstash-mcp
93
+ ```
94
+
95
+ ### Troubleshooting
96
+
97
+ #### Common Issues
98
+
99
+ Your mcp client might have trouble finding the right binaries because of the differences between your shell and system `PATH`.
100
+
101
+ To fix this, you can get the full path of the binaries by running `which npx` or `which docker` in your shell, and replace the `npx` or `docker` command in the MCP config with the full binary path.
102
+
103
+ #### Node Version Manager
104
+
105
+ If you are using a node version manager like nvm or fnm, please check [this issue](https://github.com/modelcontextprotocol/servers/issues/64#issuecomment-2530337743). You should change the `node` command in the MCP config to the absolute path of the node binary.
106
+
107
+ #### Additional Troubleshooting
108
+
109
+ See the [troubleshooting guide](https://modelcontextprotocol.io/quickstart#troubleshooting) in the MCP documentation. You can also reach out to us at [Discord](https://discord.com/invite/w9SenAtbme).
42
110
 
43
111
  ## Tools
44
112
 
@@ -65,8 +133,8 @@ See the [troubleshooting guide](https://modelcontextprotocol.io/quickstart#troub
65
133
  Clone the project and run:
66
134
 
67
135
  ```bash
68
- bun install
69
- npm run watch
136
+ pnpm install
137
+ pnpm run watch
70
138
  ```
71
139
 
72
140
  This will continuously build the project and watch for changes.
@@ -85,7 +153,7 @@ This will be used for setting the Claude config and running mcp inspector.
85
153
  To install the Claude Desktop config for local development, run the following command:
86
154
 
87
155
  ```bash
88
- npm run setup
156
+ pnpm run setup
89
157
  ```
90
158
 
91
159
  This will add an `upstash` entry to your MCP config file that points to the local build of the package.
@@ -106,7 +174,7 @@ You can now use Claude Desktop to run Upstash commands.
106
174
  To view the logs from the MCP Server in real time, run the following command:
107
175
 
108
176
  ```bash
109
- npm run logs
177
+ pnpm run logs
110
178
  ```
111
179
 
112
180
  ### Testing with MCP Inspector
@@ -114,5 +182,5 @@ npm run logs
114
182
  You can also use the MCP Inspector to test the tools.
115
183
 
116
184
  ```bash
117
- npm run inspector
185
+ pnpm run inspector
118
186
  ```
package/dist/index.js CHANGED
@@ -625,7 +625,7 @@ var envEmail = process.env.UPSTASH_EMAIL;
625
625
  var USAGE_GENERAL = `Usage: npx @upstash/mcp-server (init|run) <UPSTASH_EMAIL> <UPSTASH_API_KEY>`;
626
626
  var USAGE_RUN = `Usage: npx @upstash/mcp-server run <UPSTASH_EMAIL> <UPSTASH_API_KEY>`;
627
627
  var USAGE_INIT = `Usage: npx @upstash/mcp-server init <UPSTASH_EMAIL> <UPSTASH_API_KEY>`;
628
- function parseArguments() {
628
+ async function parseArguments() {
629
629
  const [cmd, ...args] = process.argv.slice(2);
630
630
  if (!cmd) throw new Error(USAGE_GENERAL);
631
631
  else if (cmd === "init") {
@@ -637,8 +637,8 @@ function parseArguments() {
637
637
  if (!finalEmail) throw new Error(`Missing email. ${USAGE_INIT}`);
638
638
  config.apiKey = finalApiKey;
639
639
  config.email = finalEmail;
640
- testConnection();
641
- init({
640
+ await testConnection();
641
+ await init({
642
642
  executablePath: process.argv[1]
643
643
  });
644
644
  } else if (cmd === "run") {
@@ -651,11 +651,8 @@ function parseArguments() {
651
651
  log("Starting MCP server");
652
652
  config.apiKey = finalApiKey;
653
653
  config.email = finalEmail;
654
- testConnection();
655
- main().catch((error) => {
656
- console.error("Server error:", error);
657
- process.exit(1);
658
- });
654
+ await testConnection();
655
+ await main();
659
656
  } else {
660
657
  throw new Error(`Unknown command: ${cmd}. Expected 'init' or 'run'. ${USAGE_GENERAL}`);
661
658
  }
@@ -664,11 +661,9 @@ async function main() {
664
661
  const transport = new StdioServerTransport();
665
662
  await server.connect(transport);
666
663
  }
667
- try {
668
- parseArguments();
669
- } catch (error) {
664
+ parseArguments().catch((error) => {
670
665
  if (!(error instanceof Error)) throw error;
671
666
  console.error(error.message);
672
667
  process.exit(1);
673
- }
668
+ });
674
669
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/init.ts","../src/log.ts","../src/config.ts","../src/server.ts","../src/tools/utils.ts","../src/tools/redis/backup.ts","../src/middlewares.ts","../src/http.ts","../src/tools/redis/command.ts","../src/tools/redis/db.ts","../src/utils.ts","../src/tools/redis/index.ts","../src/tools/index.ts","../src/tool.ts","../src/settings.ts","../src/test-connection.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { init } from \"./init\";\nimport { log } from \"./log\";\nimport { server } from \"./server\";\nimport { config } from \"./config\";\nimport \"dotenv/config\";\nimport { testConnection } from \"./test-connection\";\n\nprocess.on(\"uncaughtException\", (error) => {\n log(\"Uncaught exception:\", error.name, error.message, error.stack);\n});\n\nprocess.on(\"unhandledRejection\", (error) => {\n if (error instanceof Error) log(\"Unhandled rejection:\", error.name, error.message, error.stack);\n else log(\"Unhandled rejection:\", error);\n});\n\nconst envApiKey = process.env.UPSTASH_API_KEY;\nconst envEmail = process.env.UPSTASH_EMAIL;\n\nconst USAGE_GENERAL = `Usage: npx @upstash/mcp-server (init|run) <UPSTASH_EMAIL> <UPSTASH_API_KEY>`;\nconst USAGE_RUN = `Usage: npx @upstash/mcp-server run <UPSTASH_EMAIL> <UPSTASH_API_KEY>`;\nconst USAGE_INIT = `Usage: npx @upstash/mcp-server init <UPSTASH_EMAIL> <UPSTASH_API_KEY>`;\n\nfunction parseArguments() {\n const [cmd, ...args] = process.argv.slice(2);\n if (!cmd) throw new Error(USAGE_GENERAL);\n else if (cmd === \"init\") {\n const [email, apiKey, ...rest] = args;\n const finalApiKey = apiKey || envApiKey;\n const finalEmail = email || envEmail;\n\n if (rest.length > 0) throw new Error(`Too many arguments. ${USAGE_INIT}`);\n if (!finalApiKey) throw new Error(`Missing API key. ${USAGE_INIT}`);\n if (!finalEmail) throw new Error(`Missing email. ${USAGE_INIT}`);\n\n config.apiKey = finalApiKey;\n config.email = finalEmail;\n\n testConnection();\n\n init({\n executablePath: process.argv[1],\n });\n } else if (cmd === \"run\") {\n const [email, apiKey, ...rest] = args;\n const finalApiKey = apiKey || envApiKey;\n const finalEmail = email || envEmail;\n\n if (!finalApiKey) throw new Error(`Missing API key. ${USAGE_RUN}`);\n if (!finalEmail) throw new Error(`Missing email. ${USAGE_RUN}`);\n if (rest.length > 0) throw new Error(`Too many arguments. ${USAGE_RUN}`);\n log(\"Starting MCP server\");\n\n config.apiKey = finalApiKey;\n config.email = finalEmail;\n\n testConnection();\n\n // Start the server\n main().catch((error) => {\n console.error(\"Server error:\", error);\n process.exit(1);\n });\n } else {\n throw new Error(`Unknown command: ${cmd}. Expected 'init' or 'run'. ${USAGE_GENERAL}`);\n }\n}\n\nasync function main() {\n const transport = new StdioServerTransport();\n await server.connect(transport);\n}\n\ntry {\n parseArguments();\n} catch (error) {\n if (!(error instanceof Error)) throw error;\n console.error(error.message);\n process.exit(1);\n}\n","/* eslint-disable unicorn/prefer-node-protocol */\nimport path from \"path\";\nimport os from \"os\";\nimport fs from \"fs\";\nimport chalk from \"chalk\";\n\nimport { log } from \"./log\";\nimport { config } from \"./config\";\n\nconst claudeConfigPath = path.join(\n os.homedir(),\n \"Library\",\n \"Application Support\",\n \"Claude\",\n \"claude_desktop_config.json\"\n);\n\nconst UPSTASH_MCP_KEY = \"upstash\";\n\nexport async function init({ executablePath }: { executablePath: string }) {\n const isLocal = executablePath.includes(\"dist/index.js\");\n const upstashConfig = isLocal\n ? {\n command: \"node\",\n args: [executablePath, \"run\", config.email, config.apiKey],\n }\n : {\n command: \"npx\",\n args: [\"-y\", \"@upstash/mcp-server\", \"run\", config.email, config.apiKey],\n };\n\n const configDir = path.dirname(claudeConfigPath);\n if (!fs.existsSync(configDir)) {\n log(chalk.blue(\"Creating Claude config directory...\"));\n fs.mkdirSync(configDir, { recursive: true });\n }\n\n const existingConfig = fs.existsSync(claudeConfigPath)\n ? (JSON.parse(fs.readFileSync(claudeConfigPath, \"utf8\")) as {\n mcpServers?: Record<string, unknown>;\n })\n : { mcpServers: {} };\n\n if (UPSTASH_MCP_KEY in (existingConfig?.mcpServers || {})) {\n log(chalk.yellow(\"Upstash entry already exists. Overriding it.\"));\n }\n\n if (isLocal) {\n log(\n chalk.yellow(\n \"Local executable detected. Using 'node' and absolute path instead of 'npx' for development.\"\n )\n );\n }\n\n const newConfig = {\n ...existingConfig,\n mcpServers: {\n ...existingConfig.mcpServers,\n [UPSTASH_MCP_KEY]: upstashConfig,\n },\n };\n\n fs.writeFileSync(claudeConfigPath, JSON.stringify(newConfig, null, 2));\n\n log(\n chalk.blue(\n \"\\n\" +\n JSON.stringify(\n {\n [UPSTASH_MCP_KEY]: upstashConfig,\n },\n null,\n 2\n ).replaceAll(config.apiKey, \"********\")\n )\n );\n log(chalk.green(`Config written to: \"${claudeConfigPath.replace(os.homedir(), \"~\")}\"`));\n}\n","export function log(...args: unknown[]) {\n const msg = `[DEBUG ${new Date().toISOString()}] ${args.map((arg) => (typeof arg === \"string\" ? arg : JSON.stringify(arg))).join(\" \")}\\n`;\n process.stderr.write(msg);\n}\n","export const config = {\n apiKey: \"\",\n email: \"\",\n};\n","import { Server } from \"@modelcontextprotocol/sdk/server/index.js\";\nimport { ListToolsRequestSchema, CallToolRequestSchema } from \"@modelcontextprotocol/sdk/types.js\";\nimport { log } from \"./log\";\nimport { tools } from \"./tools\";\nimport { convertToTools, handlerResponseToCallResult } from \"./tool\";\n\nexport const server = new Server(\n { name: \"upstash\", version: \"0.1.0\" },\n { capabilities: { tools: {} } }\n);\n\nconst toolsList = convertToTools(tools);\n\nserver.setRequestHandler(ListToolsRequestSchema, async () => {\n log(\"Received list tools request\", toolsList);\n return { tools: toolsList };\n});\n\nserver.setRequestHandler(CallToolRequestSchema, async (request) => {\n const toolName = request.params.name;\n log(\"< received tool call:\", toolName, request.params.arguments);\n try {\n if (toolName in tools) {\n const tool = tools[toolName];\n const result = await tool.handler(request.params.arguments);\n\n const response = handlerResponseToCallResult(result);\n log(\"> tool result:\", response.content.map((item) => item.text).join(\"\\n\"));\n\n return response;\n }\n throw new Error(`Unknown tool: ${toolName}`);\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error);\n log(\"> error in tool call:\", msg);\n return {\n content: [\n {\n type: \"text\",\n text: `Error: ${msg}`,\n },\n ],\n isError: true,\n };\n }\n});\n","import { z } from \"zod\";\nimport { tool } from \".\";\n\nexport const utilTools = {\n timestamps_to_date: tool({\n description: `Use this tool to convert a timestamp to a human-readable date`,\n inputSchema: z.object({\n timestamps: z.array(z.number()).describe(\"Array of timestamps to convert\"),\n }),\n handler: async ({ timestamps }) => {\n return timestamps.map((timestamp) => new Date(timestamp).toUTCString());\n },\n }),\n}","import { z } from \"zod\";\nimport { json, tool } from \"..\";\nimport { http } from \"../../http\";\nimport type { RedisBackup } from \"./types\";\n\nexport const redisBackupTools = {\n redis_database_create_backup: tool({\n description: `Create a backup of a specific Upstash redis database.\nNOTE: Ask user to choose a name for the backup`,\n inputSchema: z.object({\n database_id: z.string().describe(\"The ID of the database to create a backup for.\"),\n backup_name: z.string().describe(\"A name for the backup.\"),\n }),\n handler: async ({ database_id, backup_name }) => {\n await http.post([\"v2/redis/create-backup\", database_id], {\n name: backup_name,\n });\n\n return \"OK\";\n },\n }),\n\n redis_database_delete_backup: tool({\n description: `Delete a backup of a specific Upstash redis database.`,\n inputSchema: z.object({\n database_id: z.string().describe(\"The ID of the database to delete a backup from.\"),\n backup_id: z.string().describe(\"The ID of the backup to delete.\"),\n }),\n handler: async ({ database_id, backup_id }) => {\n await http.delete([\"v2/redis/delete-backup\", database_id, backup_id]);\n\n return \"OK\";\n },\n }),\n\n redis_database_restore_backup: tool({\n description: `Restore a backup of a specific Upstash redis database. A backup can only be restored to the same database it was created from.`,\n inputSchema: z.object({\n database_id: z.string().describe(\"The ID of the database to restore a backup to.\"),\n backup_id: z.string().describe(\"The ID of the backup to restore.\"),\n }),\n handler: async ({ database_id, backup_id }) => {\n await http.post([\"v2/redis/restore-backup\", database_id], {\n backup_id,\n });\n\n return \"OK\";\n },\n }),\n\n redis_database_list_backups: tool({\n // TODO: Add explanation for fields\n // TODO: Is this in bytes?\n description: `List all backups of a specific Upstash redis database.`,\n inputSchema: z.object({\n database_id: z.string().describe(\"The ID of the database to list backups for.\"),\n }),\n handler: async ({ database_id }) => {\n const backups = await http.get<RedisBackup[]>([\"v2/redis/list-backup\", database_id]);\n\n return json(backups);\n },\n }),\n\n redis_database_set_daily_backup: tool({\n description: `Enable or disable daily backups for a specific Upstash redis database.`,\n inputSchema: z.object({\n database_id: z\n .string()\n .describe(\"The ID of the database to enable or disable daily backups for.\"),\n enable: z.boolean().describe(\"Whether to enable or disable daily backups.\"),\n }),\n handler: async ({ database_id, enable }) => {\n await http.patch([\n `v2/redis/${enable ? \"enable-dailybackup\" : \"disable-dailybackup\"}`,\n database_id,\n ]);\n\n return \"OK\";\n },\n }),\n};\n","import type { UpstashRequest } from \"./http\";\n\ntype Middleware = (req: UpstashRequest, next: () => Promise<unknown>) => Promise<unknown>;\n\nconst formatCreationTime = (obj: unknown) => {\n if (\n obj &&\n typeof obj === \"object\" &&\n \"creation_time\" in obj &&\n typeof obj.creation_time === \"number\" &&\n obj.creation_time > 0\n ) {\n obj.creation_time = new Date(obj.creation_time * 1000).toLocaleString();\n }\n};\n\nconst middlewares: Middleware[] = [\n // Middleware to format creation_time field to human readable format\n async (req, next) => {\n const res = await next();\n if (Array.isArray(res)) {\n for (const element of res) {\n formatCreationTime(element);\n }\n } else {\n formatCreationTime(res);\n }\n return res;\n },\n];\n\nexport const applyMiddlewares = async (\n req: UpstashRequest,\n func: (req: UpstashRequest) => Promise<unknown>\n) => {\n let next = async () => func(req);\n for (const middleware of middlewares.reverse()) {\n const prevNext = next;\n next = async () => middleware(req, prevNext);\n }\n return next();\n};\n","import { config } from \"./config\";\nimport { log } from \"./log\";\nimport { applyMiddlewares } from \"./middlewares\";\nimport type { RequestInit } from \"node-fetch\";\nimport fetch from \"node-fetch\";\n\nexport type UpstashRequest = {\n method: string;\n path?: string[] | string;\n /**\n * Request body will be serialized to json\n */\n body?: unknown;\n};\n\ntype HttpClientConfig = {\n baseUrl: string;\n};\n\nclass HttpClient {\n private readonly baseUrl: string;\n\n public constructor(config: HttpClientConfig) {\n this.baseUrl = config.baseUrl.replace(/\\/$/, \"\");\n }\n\n public async get<TResponse>(path: string[] | string): Promise<TResponse> {\n return this.requestWithMiddleware<TResponse>({ method: \"GET\", path });\n }\n\n public async post<TResponse>(path: string[] | string, body: unknown): Promise<TResponse> {\n return this.requestWithMiddleware<TResponse>({ method: \"POST\", path, body });\n }\n\n public async patch<TResponse>(path: string[] | string, body?: unknown): Promise<TResponse> {\n return this.requestWithMiddleware<TResponse>({ method: \"PATCH\", path, body });\n }\n\n public async delete<TResponse>(path: string[] | string): Promise<TResponse> {\n return this.requestWithMiddleware<TResponse>({ method: \"DELETE\", path });\n }\n\n private async requestWithMiddleware<TResponse>(req: UpstashRequest): Promise<TResponse> {\n const res = await applyMiddlewares(req, async (req) => {\n return this.request<TResponse>(req);\n });\n\n return res as TResponse;\n }\n\n private async request<TResponse>(req: UpstashRequest): Promise<TResponse> {\n if (!req.path) {\n req.path = [];\n } else if (typeof req.path === \"string\") {\n req.path = [req.path];\n }\n\n const url = [this.baseUrl, ...req.path].join(\"/\");\n const token = [config.email, config.apiKey].join(\":\");\n\n const init: RequestInit = {\n method: req.method,\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Basic ${Buffer.from(token).toString(\"base64\")}`,\n },\n };\n\n if (req.method !== \"GET\") {\n init.body = JSON.stringify(req.body);\n }\n\n log(\"Sending request\", {\n url,\n ...init,\n headers: { ...init.headers, Authorization: \"***\" },\n });\n\n // fetch is defined by isomorphic fetch\n const res = await fetch(url, init);\n if (!res.ok) {\n throw new Error(`Request failed (${res.status} ${res.statusText}): ${await res.text()}`);\n }\n return (await res.json()) as TResponse;\n }\n}\n\nexport const http = new HttpClient({ baseUrl: \"https://api.upstash.com\" });\n","import { z } from \"zod\";\nimport { json, tool } from \"..\";\nimport { log } from \"../../log\";\nimport fetch from \"node-fetch\";\n\ntype RedisCommandResult =\n | {\n result: unknown;\n }\n | {\n error: string;\n };\n\nexport const redisCommandTools = {\n redis_database_run_single_redis_command: tool({\n description: `Run a single Redis command on a specific Upstash redis database.\nNOTE: For discovery, use SCAN over KEYS. Use TYPE to get the type of a key.\nNOTE: SCAN cursor [MATCH pattern] [COUNT count] [TYPE type]`,\n inputSchema: z.object({\n database_rest_url: z\n .string()\n .describe(\"The REST URL of the database. Example: https://***.upstash.io\"),\n database_rest_token: z.string().describe(\"The REST token of the database.\"),\n command: z\n .array(z.string())\n .describe(\"The Redis command to run. Example: ['SET', 'foo', 'bar', 'EX', 100]\"),\n }),\n\n handler: async ({ database_rest_url, database_rest_token, command }) => {\n const req = await fetch(database_rest_url, {\n method: \"POST\",\n body: JSON.stringify(command),\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${database_rest_token}`,\n },\n });\n\n const result = (await req.json()) as RedisCommandResult;\n\n log(\"command result:\", result);\n\n if (\"error\" in result) {\n throw new Error(\"Redis error: \" + result.error);\n }\n\n const isScanCommand = command[0].toLocaleLowerCase().includes(\"scan\");\n const messages = [json(result)];\n\n if (isScanCommand)\n messages.push(`NOTE: Use the returned cursor to get the next set of keys.\nNOTE: The result might be too large to be returned. If applicable, stop after the second SCAN command and ask the user if they want to continue.`);\n\n return messages;\n },\n }),\n\n redis_database_run_multiple_redis_commands: tool({\n description: `Run multiple Redis commands on a specific Upstash redis database`,\n inputSchema: z.object({\n database_rest_url: z\n .string()\n .describe(\"The REST URL of the database. Example: https://***.upstash.io\"),\n database_rest_token: z.string().describe(\"The REST token of the database.\"),\n commands: z\n .array(z.array(z.string()))\n .describe(\"The Redis commands to run. Example: [['SET', 'foo', 'bar'], ['GET', 'foo']]\"),\n }),\n\n handler: async ({ database_rest_url, database_rest_token, commands }) => {\n const req = await fetch(database_rest_url + \"/pipeline\", {\n method: \"POST\",\n body: JSON.stringify(commands),\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${database_rest_token}`,\n },\n });\n\n const result = (await req.json()) as RedisCommandResult[];\n\n log(\"commands result:\", result);\n\n if (result.some((r) => \"error\" in r)) {\n throw new Error(\"Some commands in the pipeline resulted in an error:\\n\" + json(result));\n }\n\n return json(result);\n },\n }),\n};\n","import { z } from \"zod\";\nimport { json, tool } from \"..\";\nimport { http } from \"../../http\";\nimport type { RedisDatabase, RedisUsageResponse, UsageData } from \"./types\";\nimport { pruneFalsy } from \"../../utils\";\n\nconst readRegionSchema = z.union([\n z.literal(\"us-east-1\"),\n z.literal(\"us-west-1\"),\n z.literal(\"us-west-2\"),\n z.literal(\"eu-west-1\"),\n z.literal(\"eu-central-1\"),\n z.literal(\"ap-southeast-1\"),\n z.literal(\"ap-southeast-2\"),\n z.literal(\"sa-east-1\"),\n]);\n\nconst GENERIC_DATABASE_NOTES =\n \"\\nNOTE: Don't show the database ID from the response to the user unless explicitly asked or needed.\\n\";\n\nexport const redisDbOpsTools = {\n redis_database_create_new: tool({\n description: `Create a new Upstash redis database. \nNOTE: Ask user for the region and name of the database.${GENERIC_DATABASE_NOTES}`,\n inputSchema: z.object({\n name: z.string().describe(\"Name of the database.\"),\n primary_region: readRegionSchema.describe(`Primary Region of the Global Database.`),\n read_regions: z\n .array(readRegionSchema)\n .optional()\n .describe(`Array of read regions of the db`),\n }),\n handler: async ({ name, primary_region, read_regions }) => {\n const newDb = await http.post<RedisDatabase>(\"v2/redis/database\", {\n name,\n region: \"global\",\n primary_region,\n read_regions,\n });\n\n return [\n json(newDb),\n `Upstash console url: https://console.upstash.com/redis/${newDb.database_id}`,\n ];\n },\n }),\n\n redis_database_delete: tool({\n description: `Delete an Upstash redis database.`,\n inputSchema: z.object({\n database_id: z.string().describe(\"The ID of the database to delete.\"),\n }),\n handler: async ({ database_id }) => {\n await http.delete([\"v2/redis/database\", database_id]);\n\n return \"Database deleted successfully.\";\n },\n }),\n\n redis_database_list_databases: tool({\n description: `List all Upstash redis databases. Only their names and ids.${GENERIC_DATABASE_NOTES}`,\n handler: async () => {\n const dbs = await http.get<RedisDatabase[]>(\"v2/redis/databases\");\n\n const messages = [\n json(\n dbs.map((db) => {\n const result = {\n database_id: db.database_id,\n database_name: db.database_name,\n state: db.state === \"active\" ? undefined : db.state,\n };\n return pruneFalsy(result);\n })\n ),\n ];\n\n if (dbs.length > 2)\n messages.push(\n `NOTE: If the user did not specify a database name for the next command, ask them to choose a database from the list.`\n );\n messages.push(\n \"NOTE: If the user wants to see dbs in another team, mention that they need to create a new management api key for that team and initialize MCP server with the newly created key.\"\n );\n\n return messages;\n },\n }),\n\n redis_database_get_details: tool({\n description: `Get further details of a specific Upstash redis database. Includes all details of the database including usage statistics.\ndb_disk_threshold: Total disk usage limit.\ndb_memory_threshold: Maximum memory usage.\ndb_daily_bandwidth_limit: Maximum daily network bandwidth usage.\ndb_request_limit: Total number of commands allowed.\nAll sizes are in bytes\n${GENERIC_DATABASE_NOTES}\n `,\n inputSchema: z.object({\n database_id: z.string().describe(\"The ID of the database to get details for.\"),\n }),\n handler: async ({ database_id }) => {\n const db = await http.get<RedisDatabase>([\"v2/redis/database\", database_id]);\n\n return json(db);\n },\n }),\n\n redis_database_update_regions: tool({\n description: `Update the read regions of an Upstash redis database.`,\n inputSchema: z.object({\n id: z.string().describe(\"The ID of your database.\"),\n read_regions: z\n .array(readRegionSchema)\n .describe(\n \"Array of the new read regions of the database. This will replace the old regions array. Available regions: us-east-1, us-west-1, us-west-2, eu-west-1, eu-central-1, ap-southeast-1, ap-southeast-2, sa-east-1\"\n ),\n }),\n handler: async ({ id, read_regions }) => {\n const updatedDb = await http.post<RedisDatabase>([\"v2/redis/update-regions\", id], {\n read_regions,\n });\n\n return json(updatedDb);\n },\n }),\n\n redis_database_reset_password: tool({\n description: `Reset the password of an Upstash redis database.`,\n inputSchema: z.object({\n id: z.string().describe(\"The ID of your database.\"),\n }),\n handler: async ({ id }) => {\n const updatedDb = await http.post<RedisDatabase>([\"v2/redis/reset-password\", id], {});\n\n return json(updatedDb);\n },\n }),\n\n redis_database_get_usage_last_5_days: tool({\n description: `Get PRECISE command count and bandwidth usage statistics of an Upstash redis database over the last 5 days. This is a precise stat, not an average.\nNOTE: Ask user first if they want to see stats for each database seperately or just for one.`,\n inputSchema: z.object({\n id: z.string().describe(\"The ID of your database.\"),\n }),\n handler: async ({ id }) => {\n const stats = await http.get<RedisUsageResponse>([\"v2/redis/stats\", `${id}?period=3h`]);\n\n return [\n json({\n days: stats.days,\n command_usage: stats.dailyrequests,\n bandwidth_usage: stats.bandwidths,\n }),\n `NOTE: Times are calculated according to UTC+0`,\n ];\n },\n }),\n\n redis_database_get_stats: tool({\n description: `Get SAMPLED usage statistics of an Upstash redis database over a period of time (1h, 3h, 12h, 1d, 3d, 7d). Use this to check for peak usages and latency problems.\nIncludes: read_latency_mean, write_latency_mean, keyspace, throughput (cmds/sec), diskusage\nNOTE: If the user does not specify which stat to get, use throughput as default.`,\n inputSchema: z.object({\n id: z.string().describe(\"The ID of your database.\"),\n period: z\n .union([\n z.literal(\"1h\"),\n z.literal(\"3h\"),\n z.literal(\"12h\"),\n z.literal(\"1d\"),\n z.literal(\"3d\"),\n z.literal(\"7d\"),\n ])\n .describe(\"The period of the stats.\"),\n type: z\n .union([\n z.literal(\"read_latency_mean\"),\n z.literal(\"write_latency_mean\"),\n z.literal(\"keyspace\").describe(\"Number of keys in db\"),\n z\n .literal(\"throughput\")\n .describe(\"commands per second (sampled), calculate area for estimated count\"),\n z.literal(\"diskusage\").describe(\"Current disk usage in bytes\"),\n ])\n .describe(\"The type of stat to get\"),\n }),\n handler: async ({ id, period, type }) => {\n const stats = await http.get<RedisUsageResponse>([\n \"v2/redis/stats\",\n `${id}?period=${period}`,\n ]);\n\n const stat = stats[type];\n\n if (!Array.isArray(stat))\n throw new Error(\n `Invalid key provided: ${type}. Valid keys are: ${Object.keys(stats).join(\", \")}`\n );\n\n return [\n JSON.stringify(parseUsageData(stat)),\n `NOTE: Use the timestamps_to_date tool to parse timestamps if needed`,\n `NOTE: Don't try to plot multiple stats in the same chart`,\n ];\n },\n }),\n};\n\nconst parseUsageData = (data: UsageData) => {\n if (!data) return \"NO DATA\";\n if (!Array.isArray(data)) return \"INVALID DATA\";\n if (data.length === 0 || data.length === 1) return \"NO DATA\";\n const filteredData = data.filter((d) => d.x && d.y);\n return {\n start: filteredData[0].x,\n // last one can be null, so use the second last\n // eslint-disable-next-line unicorn/prefer-at\n end: filteredData[filteredData.length - 1]?.x,\n data: data.map((d) => [new Date(d.x).getTime(), d.y]),\n };\n};\n","export function pruneFalsy(obj: Record<string, any>) {\n return Object.fromEntries(Object.entries(obj).filter(([, value]) => value));\n}\n","import { utilTools } from \"../utils\";\nimport { redisBackupTools } from \"./backup\";\nimport { redisCommandTools } from \"./command\";\nimport { redisDbOpsTools } from \"./db\";\n\nexport const redisTools = {\n ...redisDbOpsTools,\n ...redisBackupTools,\n ...redisCommandTools,\n ...utilTools,\n};\n","import type { ZodSchema } from \"zod\";\nimport type { CustomTool } from \"../tool\";\nimport { redisTools } from \"./redis\";\n\nexport const json = (json: unknown) =>\n typeof json === \"string\" ? json : JSON.stringify(json, null, 2);\n\nexport const tools = {\n ...redisTools,\n} as unknown as Record<string, CustomTool>;\n\n// Only used for type inference\nexport function tool<TSchema extends ZodSchema>(tool: CustomTool<TSchema>) {\n return tool;\n}\n","import type { CallToolResultSchema } from \"@modelcontextprotocol/sdk/types.js\";\nimport type { ZodSchema } from \"zod\";\nimport { z } from \"zod\";\nimport { zodToJsonSchema } from \"zod-to-json-schema\";\nimport { MAX_MESSAGE_LENGTH } from \"./settings\";\n\ntype HandlerResponse = string | string[] | z.infer<typeof CallToolResultSchema>;\n\nexport type CustomTool<TSchema extends ZodSchema = ZodSchema> = {\n description: string;\n\n /**\n * Zod schema for the input of the tool.\n */\n inputSchema?: TSchema;\n\n /**\n * The handler function for the tool.\n * @param input Parsed input according to the input schema.\n * @returns\n * If result is a string, it will be displayed as a single text block.\n * If result is an array of strings, each string will be displayed as a separate text block.\n * You can also return a CallToolResult object to display more complex content.\n */\n handler: (input: z.infer<TSchema>) => Promise<HandlerResponse>;\n};\n\nexport function handlerResponseToCallResult(\n response: HandlerResponse\n): z.infer<typeof CallToolResultSchema> {\n if (typeof response === \"string\" || Array.isArray(response)) {\n const array = Array.isArray(response) ? response : [response];\n\n // Truncate messages that are too long\n const truncatedArray = array.map((item) =>\n item.length > MAX_MESSAGE_LENGTH\n ? `${item.slice(0, MAX_MESSAGE_LENGTH)}... (MESSAGE TRUNCATED, MENTION THIS TO USER)`\n : item\n );\n\n return {\n content: truncatedArray.map((text) => ({ type: \"text\", text })),\n };\n } else return response;\n}\n\nfunction convertToJsonSchema(schema: ZodSchema) {\n const jsonSchema = zodToJsonSchema(schema);\n delete jsonSchema.$schema;\n\n // Remove additionalProperties field from all objects, as it's not needed\n const removeAdditionalProperties = (schema: any) => {\n if (schema.type !== \"object\") return;\n\n delete schema.additionalProperties;\n for (const value of Object.values(schema.properties)) {\n removeAdditionalProperties(value);\n }\n };\n\n removeAdditionalProperties(jsonSchema);\n\n return jsonSchema;\n}\n\nexport function convertToTools(tools: Record<string, CustomTool>) {\n return Object.entries(tools).map(([name, tool]) => ({\n name,\n description: tool.description,\n inputSchema: convertToJsonSchema(tool.inputSchema ?? z.object({})),\n }));\n}\n","export const MAX_MESSAGE_LENGTH = 8000;\n","import { http } from \"./http\";\nimport { log } from \"./log\";\n\nexport async function testConnection() {\n log(\"๐Ÿงช Testing connection to Upstash API\");\n // TODO: Test the connection to the Upstash API here\n // to check if the token is valid\n const res = await http.get<[]>(\"v2/teams\");\n\n if (!Array.isArray(res))\n throw new Error(\"Invalid response from Upstash API. Check your API key and email.\");\n\n log(\"โœ… Connection to Upstash API is successful\");\n}\n"],"mappings":"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","names":["z","config","path","req","init","z","z","fetch","z","z","z","json","tool","z","schema","tools","tool","z","tool"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/init.ts","../src/log.ts","../src/config.ts","../src/server.ts","../src/tools/utils.ts","../src/tools/redis/backup.ts","../src/middlewares.ts","../src/http.ts","../src/tools/redis/command.ts","../src/tools/redis/db.ts","../src/utils.ts","../src/tools/redis/index.ts","../src/tools/index.ts","../src/tool.ts","../src/settings.ts","../src/test-connection.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { init } from \"./init\";\nimport { log } from \"./log\";\nimport { server } from \"./server\";\nimport { config } from \"./config\";\nimport \"dotenv/config\";\nimport { testConnection } from \"./test-connection\";\n\nprocess.on(\"uncaughtException\", (error) => {\n log(\"Uncaught exception:\", error.name, error.message, error.stack);\n});\n\nprocess.on(\"unhandledRejection\", (error) => {\n if (error instanceof Error) log(\"Unhandled rejection:\", error.name, error.message, error.stack);\n else log(\"Unhandled rejection:\", error);\n});\n\nconst envApiKey = process.env.UPSTASH_API_KEY;\nconst envEmail = process.env.UPSTASH_EMAIL;\n\nconst USAGE_GENERAL = `Usage: npx @upstash/mcp-server (init|run) <UPSTASH_EMAIL> <UPSTASH_API_KEY>`;\nconst USAGE_RUN = `Usage: npx @upstash/mcp-server run <UPSTASH_EMAIL> <UPSTASH_API_KEY>`;\nconst USAGE_INIT = `Usage: npx @upstash/mcp-server init <UPSTASH_EMAIL> <UPSTASH_API_KEY>`;\n\nasync function parseArguments() {\n const [cmd, ...args] = process.argv.slice(2);\n if (!cmd) throw new Error(USAGE_GENERAL);\n else if (cmd === \"init\") {\n const [email, apiKey, ...rest] = args;\n const finalApiKey = apiKey || envApiKey;\n const finalEmail = email || envEmail;\n\n if (rest.length > 0) throw new Error(`Too many arguments. ${USAGE_INIT}`);\n if (!finalApiKey) throw new Error(`Missing API key. ${USAGE_INIT}`);\n if (!finalEmail) throw new Error(`Missing email. ${USAGE_INIT}`);\n\n config.apiKey = finalApiKey;\n config.email = finalEmail;\n\n await testConnection();\n\n await init({\n executablePath: process.argv[1],\n });\n } else if (cmd === \"run\") {\n const [email, apiKey, ...rest] = args;\n const finalApiKey = apiKey || envApiKey;\n const finalEmail = email || envEmail;\n\n if (!finalApiKey) throw new Error(`Missing API key. ${USAGE_RUN}`);\n if (!finalEmail) throw new Error(`Missing email. ${USAGE_RUN}`);\n if (rest.length > 0) throw new Error(`Too many arguments. ${USAGE_RUN}`);\n log(\"Starting MCP server\");\n\n config.apiKey = finalApiKey;\n config.email = finalEmail;\n\n await testConnection();\n\n // Start the server\n await main();\n } else {\n throw new Error(`Unknown command: ${cmd}. Expected 'init' or 'run'. ${USAGE_GENERAL}`);\n }\n}\n\nasync function main() {\n const transport = new StdioServerTransport();\n await server.connect(transport);\n}\n\n// eslint-disable-next-line unicorn/prefer-top-level-await\nparseArguments().catch((error) => {\n if (!(error instanceof Error)) throw error;\n console.error(error.message);\n process.exit(1);\n});\n","/* eslint-disable unicorn/prefer-node-protocol */\nimport path from \"path\";\nimport os from \"os\";\nimport fs from \"fs\";\nimport chalk from \"chalk\";\n\nimport { log } from \"./log\";\nimport { config } from \"./config\";\n\nconst claudeConfigPath = path.join(\n os.homedir(),\n \"Library\",\n \"Application Support\",\n \"Claude\",\n \"claude_desktop_config.json\"\n);\n\nconst UPSTASH_MCP_KEY = \"upstash\";\n\nexport async function init({ executablePath }: { executablePath: string }) {\n const isLocal = executablePath.includes(\"dist/index.js\");\n const upstashConfig = isLocal\n ? {\n command: \"node\",\n args: [executablePath, \"run\", config.email, config.apiKey],\n }\n : {\n command: \"npx\",\n args: [\"-y\", \"@upstash/mcp-server\", \"run\", config.email, config.apiKey],\n };\n\n const configDir = path.dirname(claudeConfigPath);\n if (!fs.existsSync(configDir)) {\n log(chalk.blue(\"Creating Claude config directory...\"));\n fs.mkdirSync(configDir, { recursive: true });\n }\n\n const existingConfig = fs.existsSync(claudeConfigPath)\n ? (JSON.parse(fs.readFileSync(claudeConfigPath, \"utf8\")) as {\n mcpServers?: Record<string, unknown>;\n })\n : { mcpServers: {} };\n\n if (UPSTASH_MCP_KEY in (existingConfig?.mcpServers || {})) {\n log(chalk.yellow(\"Upstash entry already exists. Overriding it.\"));\n }\n\n if (isLocal) {\n log(\n chalk.yellow(\n \"Local executable detected. Using 'node' and absolute path instead of 'npx' for development.\"\n )\n );\n }\n\n const newConfig = {\n ...existingConfig,\n mcpServers: {\n ...existingConfig.mcpServers,\n [UPSTASH_MCP_KEY]: upstashConfig,\n },\n };\n\n fs.writeFileSync(claudeConfigPath, JSON.stringify(newConfig, null, 2));\n\n log(\n chalk.blue(\n \"\\n\" +\n JSON.stringify(\n {\n [UPSTASH_MCP_KEY]: upstashConfig,\n },\n null,\n 2\n ).replaceAll(config.apiKey, \"********\")\n )\n );\n log(chalk.green(`Config written to: \"${claudeConfigPath.replace(os.homedir(), \"~\")}\"`));\n}\n","export function log(...args: unknown[]) {\n const msg = `[DEBUG ${new Date().toISOString()}] ${args.map((arg) => (typeof arg === \"string\" ? arg : JSON.stringify(arg))).join(\" \")}\\n`;\n process.stderr.write(msg);\n}\n","export const config = {\n apiKey: \"\",\n email: \"\",\n};\n","import { Server } from \"@modelcontextprotocol/sdk/server/index.js\";\nimport { ListToolsRequestSchema, CallToolRequestSchema } from \"@modelcontextprotocol/sdk/types.js\";\nimport { log } from \"./log\";\nimport { tools } from \"./tools\";\nimport { convertToTools, handlerResponseToCallResult } from \"./tool\";\n\nexport const server = new Server(\n { name: \"upstash\", version: \"0.1.0\" },\n { capabilities: { tools: {} } }\n);\n\nconst toolsList = convertToTools(tools);\n\nserver.setRequestHandler(ListToolsRequestSchema, async () => {\n log(\"Received list tools request\", toolsList);\n return { tools: toolsList };\n});\n\nserver.setRequestHandler(CallToolRequestSchema, async (request) => {\n const toolName = request.params.name;\n log(\"< received tool call:\", toolName, request.params.arguments);\n try {\n if (toolName in tools) {\n const tool = tools[toolName];\n const result = await tool.handler(request.params.arguments);\n\n const response = handlerResponseToCallResult(result);\n log(\"> tool result:\", response.content.map((item) => item.text).join(\"\\n\"));\n\n return response;\n }\n throw new Error(`Unknown tool: ${toolName}`);\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error);\n log(\"> error in tool call:\", msg);\n return {\n content: [\n {\n type: \"text\",\n text: `Error: ${msg}`,\n },\n ],\n isError: true,\n };\n }\n});\n","import { z } from \"zod\";\nimport { tool } from \".\";\n\nexport const utilTools = {\n timestamps_to_date: tool({\n description: `Use this tool to convert a timestamp to a human-readable date`,\n inputSchema: z.object({\n timestamps: z.array(z.number()).describe(\"Array of timestamps to convert\"),\n }),\n handler: async ({ timestamps }) => {\n return timestamps.map((timestamp) => new Date(timestamp).toUTCString());\n },\n }),\n}","import { z } from \"zod\";\nimport { json, tool } from \"..\";\nimport { http } from \"../../http\";\nimport type { RedisBackup } from \"./types\";\n\nexport const redisBackupTools = {\n redis_database_create_backup: tool({\n description: `Create a backup of a specific Upstash redis database.\nNOTE: Ask user to choose a name for the backup`,\n inputSchema: z.object({\n database_id: z.string().describe(\"The ID of the database to create a backup for.\"),\n backup_name: z.string().describe(\"A name for the backup.\"),\n }),\n handler: async ({ database_id, backup_name }) => {\n await http.post([\"v2/redis/create-backup\", database_id], {\n name: backup_name,\n });\n\n return \"OK\";\n },\n }),\n\n redis_database_delete_backup: tool({\n description: `Delete a backup of a specific Upstash redis database.`,\n inputSchema: z.object({\n database_id: z.string().describe(\"The ID of the database to delete a backup from.\"),\n backup_id: z.string().describe(\"The ID of the backup to delete.\"),\n }),\n handler: async ({ database_id, backup_id }) => {\n await http.delete([\"v2/redis/delete-backup\", database_id, backup_id]);\n\n return \"OK\";\n },\n }),\n\n redis_database_restore_backup: tool({\n description: `Restore a backup of a specific Upstash redis database. A backup can only be restored to the same database it was created from.`,\n inputSchema: z.object({\n database_id: z.string().describe(\"The ID of the database to restore a backup to.\"),\n backup_id: z.string().describe(\"The ID of the backup to restore.\"),\n }),\n handler: async ({ database_id, backup_id }) => {\n await http.post([\"v2/redis/restore-backup\", database_id], {\n backup_id,\n });\n\n return \"OK\";\n },\n }),\n\n redis_database_list_backups: tool({\n // TODO: Add explanation for fields\n // TODO: Is this in bytes?\n description: `List all backups of a specific Upstash redis database.`,\n inputSchema: z.object({\n database_id: z.string().describe(\"The ID of the database to list backups for.\"),\n }),\n handler: async ({ database_id }) => {\n const backups = await http.get<RedisBackup[]>([\"v2/redis/list-backup\", database_id]);\n\n return json(backups);\n },\n }),\n\n redis_database_set_daily_backup: tool({\n description: `Enable or disable daily backups for a specific Upstash redis database.`,\n inputSchema: z.object({\n database_id: z\n .string()\n .describe(\"The ID of the database to enable or disable daily backups for.\"),\n enable: z.boolean().describe(\"Whether to enable or disable daily backups.\"),\n }),\n handler: async ({ database_id, enable }) => {\n await http.patch([\n `v2/redis/${enable ? \"enable-dailybackup\" : \"disable-dailybackup\"}`,\n database_id,\n ]);\n\n return \"OK\";\n },\n }),\n};\n","import type { UpstashRequest } from \"./http\";\n\ntype Middleware = (req: UpstashRequest, next: () => Promise<unknown>) => Promise<unknown>;\n\nconst formatCreationTime = (obj: unknown) => {\n if (\n obj &&\n typeof obj === \"object\" &&\n \"creation_time\" in obj &&\n typeof obj.creation_time === \"number\" &&\n obj.creation_time > 0\n ) {\n obj.creation_time = new Date(obj.creation_time * 1000).toLocaleString();\n }\n};\n\nconst middlewares: Middleware[] = [\n // Middleware to format creation_time field to human readable format\n async (req, next) => {\n const res = await next();\n if (Array.isArray(res)) {\n for (const element of res) {\n formatCreationTime(element);\n }\n } else {\n formatCreationTime(res);\n }\n return res;\n },\n];\n\nexport const applyMiddlewares = async (\n req: UpstashRequest,\n func: (req: UpstashRequest) => Promise<unknown>\n) => {\n let next = async () => func(req);\n for (const middleware of middlewares.reverse()) {\n const prevNext = next;\n next = async () => middleware(req, prevNext);\n }\n return next();\n};\n","import { config } from \"./config\";\nimport { log } from \"./log\";\nimport { applyMiddlewares } from \"./middlewares\";\nimport type { RequestInit } from \"node-fetch\";\nimport fetch from \"node-fetch\";\n\nexport type UpstashRequest = {\n method: string;\n path?: string[] | string;\n /**\n * Request body will be serialized to json\n */\n body?: unknown;\n};\n\ntype HttpClientConfig = {\n baseUrl: string;\n};\n\nclass HttpClient {\n private readonly baseUrl: string;\n\n public constructor(config: HttpClientConfig) {\n this.baseUrl = config.baseUrl.replace(/\\/$/, \"\");\n }\n\n public async get<TResponse>(path: string[] | string): Promise<TResponse> {\n return this.requestWithMiddleware<TResponse>({ method: \"GET\", path });\n }\n\n public async post<TResponse>(path: string[] | string, body: unknown): Promise<TResponse> {\n return this.requestWithMiddleware<TResponse>({ method: \"POST\", path, body });\n }\n\n public async patch<TResponse>(path: string[] | string, body?: unknown): Promise<TResponse> {\n return this.requestWithMiddleware<TResponse>({ method: \"PATCH\", path, body });\n }\n\n public async delete<TResponse>(path: string[] | string): Promise<TResponse> {\n return this.requestWithMiddleware<TResponse>({ method: \"DELETE\", path });\n }\n\n private async requestWithMiddleware<TResponse>(req: UpstashRequest): Promise<TResponse> {\n const res = await applyMiddlewares(req, async (req) => {\n return this.request<TResponse>(req);\n });\n\n return res as TResponse;\n }\n\n private async request<TResponse>(req: UpstashRequest): Promise<TResponse> {\n if (!req.path) {\n req.path = [];\n } else if (typeof req.path === \"string\") {\n req.path = [req.path];\n }\n\n const url = [this.baseUrl, ...req.path].join(\"/\");\n const token = [config.email, config.apiKey].join(\":\");\n\n const init: RequestInit = {\n method: req.method,\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Basic ${Buffer.from(token).toString(\"base64\")}`,\n },\n };\n\n if (req.method !== \"GET\") {\n init.body = JSON.stringify(req.body);\n }\n\n log(\"Sending request\", {\n url,\n ...init,\n headers: { ...init.headers, Authorization: \"***\" },\n });\n\n // fetch is defined by isomorphic fetch\n const res = await fetch(url, init);\n if (!res.ok) {\n throw new Error(`Request failed (${res.status} ${res.statusText}): ${await res.text()}`);\n }\n return (await res.json()) as TResponse;\n }\n}\n\nexport const http = new HttpClient({ baseUrl: \"https://api.upstash.com\" });\n","import { z } from \"zod\";\nimport { json, tool } from \"..\";\nimport { log } from \"../../log\";\nimport fetch from \"node-fetch\";\n\ntype RedisCommandResult =\n | {\n result: unknown;\n }\n | {\n error: string;\n };\n\nexport const redisCommandTools = {\n redis_database_run_single_redis_command: tool({\n description: `Run a single Redis command on a specific Upstash redis database.\nNOTE: For discovery, use SCAN over KEYS. Use TYPE to get the type of a key.\nNOTE: SCAN cursor [MATCH pattern] [COUNT count] [TYPE type]`,\n inputSchema: z.object({\n database_rest_url: z\n .string()\n .describe(\"The REST URL of the database. Example: https://***.upstash.io\"),\n database_rest_token: z.string().describe(\"The REST token of the database.\"),\n command: z\n .array(z.string())\n .describe(\"The Redis command to run. Example: ['SET', 'foo', 'bar', 'EX', 100]\"),\n }),\n\n handler: async ({ database_rest_url, database_rest_token, command }) => {\n const req = await fetch(database_rest_url, {\n method: \"POST\",\n body: JSON.stringify(command),\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${database_rest_token}`,\n },\n });\n\n const result = (await req.json()) as RedisCommandResult;\n\n log(\"command result:\", result);\n\n if (\"error\" in result) {\n throw new Error(\"Redis error: \" + result.error);\n }\n\n const isScanCommand = command[0].toLocaleLowerCase().includes(\"scan\");\n const messages = [json(result)];\n\n if (isScanCommand)\n messages.push(`NOTE: Use the returned cursor to get the next set of keys.\nNOTE: The result might be too large to be returned. If applicable, stop after the second SCAN command and ask the user if they want to continue.`);\n\n return messages;\n },\n }),\n\n redis_database_run_multiple_redis_commands: tool({\n description: `Run multiple Redis commands on a specific Upstash redis database`,\n inputSchema: z.object({\n database_rest_url: z\n .string()\n .describe(\"The REST URL of the database. Example: https://***.upstash.io\"),\n database_rest_token: z.string().describe(\"The REST token of the database.\"),\n commands: z\n .array(z.array(z.string()))\n .describe(\"The Redis commands to run. Example: [['SET', 'foo', 'bar'], ['GET', 'foo']]\"),\n }),\n\n handler: async ({ database_rest_url, database_rest_token, commands }) => {\n const req = await fetch(database_rest_url + \"/pipeline\", {\n method: \"POST\",\n body: JSON.stringify(commands),\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${database_rest_token}`,\n },\n });\n\n const result = (await req.json()) as RedisCommandResult[];\n\n log(\"commands result:\", result);\n\n if (result.some((r) => \"error\" in r)) {\n throw new Error(\"Some commands in the pipeline resulted in an error:\\n\" + json(result));\n }\n\n return json(result);\n },\n }),\n};\n","import { z } from \"zod\";\nimport { json, tool } from \"..\";\nimport { http } from \"../../http\";\nimport type { RedisDatabase, RedisUsageResponse, UsageData } from \"./types\";\nimport { pruneFalsy } from \"../../utils\";\n\nconst readRegionSchema = z.union([\n z.literal(\"us-east-1\"),\n z.literal(\"us-west-1\"),\n z.literal(\"us-west-2\"),\n z.literal(\"eu-west-1\"),\n z.literal(\"eu-central-1\"),\n z.literal(\"ap-southeast-1\"),\n z.literal(\"ap-southeast-2\"),\n z.literal(\"sa-east-1\"),\n]);\n\nconst GENERIC_DATABASE_NOTES =\n \"\\nNOTE: Don't show the database ID from the response to the user unless explicitly asked or needed.\\n\";\n\nexport const redisDbOpsTools = {\n redis_database_create_new: tool({\n description: `Create a new Upstash redis database. \nNOTE: Ask user for the region and name of the database.${GENERIC_DATABASE_NOTES}`,\n inputSchema: z.object({\n name: z.string().describe(\"Name of the database.\"),\n primary_region: readRegionSchema.describe(`Primary Region of the Global Database.`),\n read_regions: z\n .array(readRegionSchema)\n .optional()\n .describe(`Array of read regions of the db`),\n }),\n handler: async ({ name, primary_region, read_regions }) => {\n const newDb = await http.post<RedisDatabase>(\"v2/redis/database\", {\n name,\n region: \"global\",\n primary_region,\n read_regions,\n });\n\n return [\n json(newDb),\n `Upstash console url: https://console.upstash.com/redis/${newDb.database_id}`,\n ];\n },\n }),\n\n redis_database_delete: tool({\n description: `Delete an Upstash redis database.`,\n inputSchema: z.object({\n database_id: z.string().describe(\"The ID of the database to delete.\"),\n }),\n handler: async ({ database_id }) => {\n await http.delete([\"v2/redis/database\", database_id]);\n\n return \"Database deleted successfully.\";\n },\n }),\n\n redis_database_list_databases: tool({\n description: `List all Upstash redis databases. Only their names and ids.${GENERIC_DATABASE_NOTES}`,\n handler: async () => {\n const dbs = await http.get<RedisDatabase[]>(\"v2/redis/databases\");\n\n const messages = [\n json(\n dbs.map((db) => {\n const result = {\n database_id: db.database_id,\n database_name: db.database_name,\n state: db.state === \"active\" ? undefined : db.state,\n };\n return pruneFalsy(result);\n })\n ),\n ];\n\n if (dbs.length > 2)\n messages.push(\n `NOTE: If the user did not specify a database name for the next command, ask them to choose a database from the list.`\n );\n messages.push(\n \"NOTE: If the user wants to see dbs in another team, mention that they need to create a new management api key for that team and initialize MCP server with the newly created key.\"\n );\n\n return messages;\n },\n }),\n\n redis_database_get_details: tool({\n description: `Get further details of a specific Upstash redis database. Includes all details of the database including usage statistics.\ndb_disk_threshold: Total disk usage limit.\ndb_memory_threshold: Maximum memory usage.\ndb_daily_bandwidth_limit: Maximum daily network bandwidth usage.\ndb_request_limit: Total number of commands allowed.\nAll sizes are in bytes\n${GENERIC_DATABASE_NOTES}\n `,\n inputSchema: z.object({\n database_id: z.string().describe(\"The ID of the database to get details for.\"),\n }),\n handler: async ({ database_id }) => {\n const db = await http.get<RedisDatabase>([\"v2/redis/database\", database_id]);\n\n return json(db);\n },\n }),\n\n redis_database_update_regions: tool({\n description: `Update the read regions of an Upstash redis database.`,\n inputSchema: z.object({\n id: z.string().describe(\"The ID of your database.\"),\n read_regions: z\n .array(readRegionSchema)\n .describe(\n \"Array of the new read regions of the database. This will replace the old regions array. Available regions: us-east-1, us-west-1, us-west-2, eu-west-1, eu-central-1, ap-southeast-1, ap-southeast-2, sa-east-1\"\n ),\n }),\n handler: async ({ id, read_regions }) => {\n const updatedDb = await http.post<RedisDatabase>([\"v2/redis/update-regions\", id], {\n read_regions,\n });\n\n return json(updatedDb);\n },\n }),\n\n redis_database_reset_password: tool({\n description: `Reset the password of an Upstash redis database.`,\n inputSchema: z.object({\n id: z.string().describe(\"The ID of your database.\"),\n }),\n handler: async ({ id }) => {\n const updatedDb = await http.post<RedisDatabase>([\"v2/redis/reset-password\", id], {});\n\n return json(updatedDb);\n },\n }),\n\n redis_database_get_usage_last_5_days: tool({\n description: `Get PRECISE command count and bandwidth usage statistics of an Upstash redis database over the last 5 days. This is a precise stat, not an average.\nNOTE: Ask user first if they want to see stats for each database seperately or just for one.`,\n inputSchema: z.object({\n id: z.string().describe(\"The ID of your database.\"),\n }),\n handler: async ({ id }) => {\n const stats = await http.get<RedisUsageResponse>([\"v2/redis/stats\", `${id}?period=3h`]);\n\n return [\n json({\n days: stats.days,\n command_usage: stats.dailyrequests,\n bandwidth_usage: stats.bandwidths,\n }),\n `NOTE: Times are calculated according to UTC+0`,\n ];\n },\n }),\n\n redis_database_get_stats: tool({\n description: `Get SAMPLED usage statistics of an Upstash redis database over a period of time (1h, 3h, 12h, 1d, 3d, 7d). Use this to check for peak usages and latency problems.\nIncludes: read_latency_mean, write_latency_mean, keyspace, throughput (cmds/sec), diskusage\nNOTE: If the user does not specify which stat to get, use throughput as default.`,\n inputSchema: z.object({\n id: z.string().describe(\"The ID of your database.\"),\n period: z\n .union([\n z.literal(\"1h\"),\n z.literal(\"3h\"),\n z.literal(\"12h\"),\n z.literal(\"1d\"),\n z.literal(\"3d\"),\n z.literal(\"7d\"),\n ])\n .describe(\"The period of the stats.\"),\n type: z\n .union([\n z.literal(\"read_latency_mean\"),\n z.literal(\"write_latency_mean\"),\n z.literal(\"keyspace\").describe(\"Number of keys in db\"),\n z\n .literal(\"throughput\")\n .describe(\"commands per second (sampled), calculate area for estimated count\"),\n z.literal(\"diskusage\").describe(\"Current disk usage in bytes\"),\n ])\n .describe(\"The type of stat to get\"),\n }),\n handler: async ({ id, period, type }) => {\n const stats = await http.get<RedisUsageResponse>([\n \"v2/redis/stats\",\n `${id}?period=${period}`,\n ]);\n\n const stat = stats[type];\n\n if (!Array.isArray(stat))\n throw new Error(\n `Invalid key provided: ${type}. Valid keys are: ${Object.keys(stats).join(\", \")}`\n );\n\n return [\n JSON.stringify(parseUsageData(stat)),\n `NOTE: Use the timestamps_to_date tool to parse timestamps if needed`,\n `NOTE: Don't try to plot multiple stats in the same chart`,\n ];\n },\n }),\n};\n\nconst parseUsageData = (data: UsageData) => {\n if (!data) return \"NO DATA\";\n if (!Array.isArray(data)) return \"INVALID DATA\";\n if (data.length === 0 || data.length === 1) return \"NO DATA\";\n const filteredData = data.filter((d) => d.x && d.y);\n return {\n start: filteredData[0].x,\n // last one can be null, so use the second last\n // eslint-disable-next-line unicorn/prefer-at\n end: filteredData[filteredData.length - 1]?.x,\n data: data.map((d) => [new Date(d.x).getTime(), d.y]),\n };\n};\n","export function pruneFalsy(obj: Record<string, any>) {\n return Object.fromEntries(Object.entries(obj).filter(([, value]) => value));\n}\n","import { utilTools } from \"../utils\";\nimport { redisBackupTools } from \"./backup\";\nimport { redisCommandTools } from \"./command\";\nimport { redisDbOpsTools } from \"./db\";\n\nexport const redisTools = {\n ...redisDbOpsTools,\n ...redisBackupTools,\n ...redisCommandTools,\n ...utilTools,\n};\n","import type { ZodSchema } from \"zod\";\nimport type { CustomTool } from \"../tool\";\nimport { redisTools } from \"./redis\";\n\nexport const json = (json: unknown) =>\n typeof json === \"string\" ? json : JSON.stringify(json, null, 2);\n\nexport const tools = {\n ...redisTools,\n} as unknown as Record<string, CustomTool>;\n\n// Only used for type inference\nexport function tool<TSchema extends ZodSchema>(tool: CustomTool<TSchema>) {\n return tool;\n}\n","import type { CallToolResultSchema } from \"@modelcontextprotocol/sdk/types.js\";\nimport type { ZodSchema } from \"zod\";\nimport { z } from \"zod\";\nimport { zodToJsonSchema } from \"zod-to-json-schema\";\nimport { MAX_MESSAGE_LENGTH } from \"./settings\";\n\ntype HandlerResponse = string | string[] | z.infer<typeof CallToolResultSchema>;\n\nexport type CustomTool<TSchema extends ZodSchema = ZodSchema> = {\n description: string;\n\n /**\n * Zod schema for the input of the tool.\n */\n inputSchema?: TSchema;\n\n /**\n * The handler function for the tool.\n * @param input Parsed input according to the input schema.\n * @returns\n * If result is a string, it will be displayed as a single text block.\n * If result is an array of strings, each string will be displayed as a separate text block.\n * You can also return a CallToolResult object to display more complex content.\n */\n handler: (input: z.infer<TSchema>) => Promise<HandlerResponse>;\n};\n\nexport function handlerResponseToCallResult(\n response: HandlerResponse\n): z.infer<typeof CallToolResultSchema> {\n if (typeof response === \"string\" || Array.isArray(response)) {\n const array = Array.isArray(response) ? response : [response];\n\n // Truncate messages that are too long\n const truncatedArray = array.map((item) =>\n item.length > MAX_MESSAGE_LENGTH\n ? `${item.slice(0, MAX_MESSAGE_LENGTH)}... (MESSAGE TRUNCATED, MENTION THIS TO USER)`\n : item\n );\n\n return {\n content: truncatedArray.map((text) => ({ type: \"text\", text })),\n };\n } else return response;\n}\n\nfunction convertToJsonSchema(schema: ZodSchema) {\n const jsonSchema = zodToJsonSchema(schema);\n delete jsonSchema.$schema;\n\n // Remove additionalProperties field from all objects, as it's not needed\n const removeAdditionalProperties = (schema: any) => {\n if (schema.type !== \"object\") return;\n\n delete schema.additionalProperties;\n for (const value of Object.values(schema.properties)) {\n removeAdditionalProperties(value);\n }\n };\n\n removeAdditionalProperties(jsonSchema);\n\n return jsonSchema;\n}\n\nexport function convertToTools(tools: Record<string, CustomTool>) {\n return Object.entries(tools).map(([name, tool]) => ({\n name,\n description: tool.description,\n inputSchema: convertToJsonSchema(tool.inputSchema ?? z.object({})),\n }));\n}\n","export const MAX_MESSAGE_LENGTH = 8000;\n","import { http } from \"./http\";\nimport { log } from \"./log\";\n\nexport async function testConnection() {\n log(\"๐Ÿงช Testing connection to Upstash API\");\n // TODO: Test the connection to the Upstash API here\n // to check if the token is valid\n const res = await http.get<[]>(\"v2/teams\");\n\n if (!Array.isArray(res))\n throw new Error(\"Invalid response from Upstash API. Check your API key and email.\");\n\n log(\"โœ… Connection to Upstash API is successful\");\n}\n"],"mappings":"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","names":["z","config","path","req","init","z","z","fetch","z","z","z","json","tool","z","schema","tools","tool","z","tool"]}
package/package.json CHANGED
@@ -1,47 +1 @@
1
- {
2
- "version": "0.0.7",
3
- "name": "@upstash/mcp-server",
4
- "description": "MCP server for Upstash",
5
- "license": "MIT",
6
- "type": "module",
7
- "bin": {
8
- "mcp-server": "./dist/index.js"
9
- },
10
- "repository": {
11
- "type": "git",
12
- "url": "git+https://github.com/upstash/mcp-server.git"
13
- },
14
- "bugs": {
15
- "url": "https://github.com/upstash/mcp-server/issues"
16
- },
17
- "scripts": {
18
- "build": "tsup && node -e \"require('fs').chmodSync('dist/index.js', '755')\"",
19
- "watch": "npm run build && tsup --watch",
20
- "inspector": "npx @modelcontextprotocol/inspector node --enable-source-maps dist/index.js run",
21
- "setup": "node ./dist/index.js init",
22
- "logs": "tail -n 20 -f ~/Library/Logs/Claude/mcp*.log",
23
- "test": "bun test",
24
- "fmt": "prettier --write .",
25
- "lint": "eslint \"**/*.{js,ts,tsx}\" --quiet --fix"
26
- },
27
- "files": [
28
- "dist"
29
- ],
30
- "devDependencies": {
31
- "@typescript-eslint/eslint-plugin": "8.4.0",
32
- "@typescript-eslint/parser": "8.4.0",
33
- "eslint": "9.10.0",
34
- "eslint-plugin-unicorn": "55.0.0",
35
- "prettier": "^3.4.2",
36
- "tsup": "^8.3.5"
37
- },
38
- "dependencies": {
39
- "@modelcontextprotocol/sdk": "^1.0.3",
40
- "@types/node": "15",
41
- "chalk": "^5.3.0",
42
- "dotenv": "^16.4.7",
43
- "node-fetch": "^3.3.2",
44
- "zod": "^3.24.1",
45
- "zod-to-json-schema": "^3.24.1"
46
- }
47
- }
1
+ { "version": "v0.1.0", "name": "@upstash/mcp-server", "description": "MCP server for Upstash", "license": "MIT", "type": "module", "bin": { "mcp-server": "./dist/index.js" }, "repository": { "type": "git", "url": "git+https://github.com/upstash/mcp-server.git" }, "bugs": { "url": "https://github.com/upstash/mcp-server/issues" }, "scripts": { "build": "tsup && node -e \"require('fs').chmodSync('dist/index.js', '755')\"", "watch": "npm run build && tsup --watch", "inspector": "npx @modelcontextprotocol/inspector node --enable-source-maps dist/index.js run", "setup": "node ./dist/index.js init", "logs": "tail -n 20 -f ~/Library/Logs/Claude/mcp*.log", "fmt": "prettier --write .", "test": "vitest", "lint": "eslint \"**/*.{js,ts,tsx}\" --quiet --fix" }, "files": [ "dist" ], "devDependencies": { "@typescript-eslint/eslint-plugin": "8.4.0", "@typescript-eslint/parser": "8.4.0", "eslint": "9.10.0", "eslint-plugin-unicorn": "55.0.0", "prettier": "^3.4.2", "tsup": "^8.3.5", "vitest": "^3.1.1" }, "dependencies": { "@modelcontextprotocol/sdk": "^1.8.0", "@types/node": "15", "chalk": "^5.3.0", "dotenv": "^16.4.7", "node-fetch": "^3.3.2", "zod": "^3.24.1", "zod-to-json-schema": "^3.24.1" } }