@upstash/context7-mcp 1.0.26 → 1.0.28
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 +187 -30
- package/dist/index.js +152 -205
- package/dist/lib/api.js +5 -3
- package/dist/lib/utils.js +20 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|

|
|
2
2
|
|
|
3
|
+
[](https://cursor.com/en/install-mcp?name=context7&config=eyJ1cmwiOiJodHRwczovL21jcC5jb250ZXh0Ny5jb20vbWNwIn0%3D) [<img alt="Install in VS Code (npx)" src="https://img.shields.io/badge/Install%20in%20VS%20Code-0098FF?style=for-the-badge&logo=visualstudiocode&logoColor=white">](https://insiders.vscode.dev/redirect?url=vscode%3Amcp%2Finstall%3F%7B%22name%22%3A%22context7%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40upstash%2Fcontext7-mcp%40latest%22%5D%7D)
|
|
4
|
+
|
|
3
5
|
# Context7 MCP - Up-to-date Code Docs For Any Prompt
|
|
4
6
|
|
|
5
7
|
[](https://context7.com) [](https://smithery.ai/server/@upstash/context7-mcp) [](https://www.npmjs.com/package/@upstash/context7-mcp) [](./LICENSE)
|
|
6
8
|
|
|
7
|
-
[](./docs/README.zh-TW.md) [](./docs/README.zh-CN.md) [](./docs/README.ja.md) [](./docs/README.ko.md) [](./docs/README.es.md) [](./docs/README.fr.md) [-purple>)](./docs/README.pt-BR.md) [](./docs/README.it.md) [](./docs/README.id-ID.md) [](./docs/README.de.md) [](./docs/README.ru.md) [](./docs/README.uk.md) [](./docs/README.tr.md) [](./docs/README.ar.md) [](./docs/README.vi.md)
|
|
9
|
+
[](./i18n/README.zh-TW.md) [](./i18n/README.zh-CN.md) [](./i18n/README.ja.md) [](./i18n/README.ko.md) [](./i18n/README.es.md) [](./i18n/README.fr.md) [-purple>)](./i18n/README.pt-BR.md) [](./i18n/README.it.md) [](./i18n/README.id-ID.md) [](./i18n/README.de.md) [](./i18n/README.ru.md) [](./i18n/README.uk.md) [](./i18n/README.tr.md) [](./i18n/README.ar.md) [](./i18n/README.vi.md)
|
|
10
10
|
|
|
11
11
|
## ❌ Without Context7
|
|
12
12
|
|
|
@@ -20,27 +20,32 @@ LLMs rely on outdated or generic information about the libraries you use. You ge
|
|
|
20
20
|
|
|
21
21
|
Context7 MCP pulls up-to-date, version-specific documentation and code examples straight from the source — and places them directly into your prompt.
|
|
22
22
|
|
|
23
|
-
Add `use context7` to your prompt
|
|
23
|
+
Add `use context7` to your prompt (or [set up a rule](#️-installation) to auto-invoke):
|
|
24
24
|
|
|
25
25
|
```txt
|
|
26
|
-
Create a Next.js middleware that checks for a valid JWT in cookies
|
|
26
|
+
Create a Next.js middleware that checks for a valid JWT in cookies
|
|
27
|
+
and redirects unauthenticated users to `/login`. use context7
|
|
27
28
|
```
|
|
28
29
|
|
|
29
30
|
```txt
|
|
30
|
-
Configure a Cloudflare Worker script to cache
|
|
31
|
+
Configure a Cloudflare Worker script to cache
|
|
32
|
+
JSON API responses for five minutes. use context7
|
|
31
33
|
```
|
|
32
34
|
|
|
33
35
|
Context7 fetches up-to-date code examples and documentation right into your LLM's context.
|
|
34
36
|
|
|
35
37
|
- 1️⃣ Write your prompt naturally
|
|
36
|
-
- 2️⃣ Tell the LLM to `use context7`
|
|
38
|
+
- 2️⃣ Tell the LLM to `use context7` (or [set up a rule](#️-installation) once)
|
|
37
39
|
- 3️⃣ Get working code answers
|
|
38
40
|
|
|
39
41
|
No tab-switching, no hallucinated APIs that don't exist, no outdated code generation.
|
|
40
42
|
|
|
43
|
+
> [!NOTE]
|
|
44
|
+
> This repository hosts the source code of Context7 MCP server. The supporting components — API backend, parsing engine, and crawling engine — are private and not part of this release.
|
|
45
|
+
|
|
41
46
|
## 📚 Adding Projects
|
|
42
47
|
|
|
43
|
-
Check out our [project addition guide](
|
|
48
|
+
Check out our [project addition guide](https://context7.com/docs/adding-libraries) to learn how to add (or update) your favorite libraries to Context7.
|
|
44
49
|
|
|
45
50
|
## 🛠️ Installation
|
|
46
51
|
|
|
@@ -50,10 +55,25 @@ Check out our [project addition guide](./docs/adding-projects.md) to learn how t
|
|
|
50
55
|
- Cursor, Claude Code, VSCode, Windsurf or another MCP Client
|
|
51
56
|
- Context7 API Key (Optional) for higher rate limits and private repositories (Get yours by creating an account at [context7.com/dashboard](https://context7.com/dashboard))
|
|
52
57
|
|
|
53
|
-
> [!
|
|
54
|
-
> **
|
|
58
|
+
> [!TIP]
|
|
59
|
+
> **Recommended Post-Setup: Add a Rule to Auto-Invoke Context7**
|
|
60
|
+
>
|
|
61
|
+
> After installing Context7 (see instructions below), enhance your workflow by adding a rule so you don't have to type `use context7` in every prompt. Define a simple rule in your MCP client's rule section to automatically invoke Context7 on any code question:
|
|
62
|
+
>
|
|
63
|
+
> - For Windsurf, in `.windsurfrules` file
|
|
64
|
+
> - For Cursor, from `Cursor Settings > Rules` section
|
|
65
|
+
> - For Claude Code, in `CLAUDE.md` file
|
|
66
|
+
> - Or the equivalent in your MCP client
|
|
67
|
+
>
|
|
68
|
+
> **Example Rule:**
|
|
55
69
|
>
|
|
56
|
-
>
|
|
70
|
+
> ```txt
|
|
71
|
+
> Always use context7 when I need code generation, setup or configuration steps, or
|
|
72
|
+
> library/API documentation. This means you should automatically use the Context7 MCP
|
|
73
|
+
> tools to resolve library id and get library docs without me having to explicitly ask.
|
|
74
|
+
> ```
|
|
75
|
+
>
|
|
76
|
+
> From then on, you'll get Context7's docs in any related conversation without typing anything extra. You can alter the rule to match your use cases.
|
|
57
77
|
|
|
58
78
|
<details>
|
|
59
79
|
<summary><b>Installing via Smithery</b></summary>
|
|
@@ -260,6 +280,76 @@ Or you can directly edit MCP servers configuration:
|
|
|
260
280
|
|
|
261
281
|
</details>
|
|
262
282
|
|
|
283
|
+
<details>
|
|
284
|
+
<summary><b>Install in Kilo Code</b></summary>
|
|
285
|
+
|
|
286
|
+
You can configure the Context7 MCP server in **Kilo Code** using either the UI or by editing your project's MCP configuration file.
|
|
287
|
+
|
|
288
|
+
Kilo Code supports two configuration levels:
|
|
289
|
+
|
|
290
|
+
- **Global MCP Configuration** — stored in `mcp_settings.json`
|
|
291
|
+
- **Project-level MCP Configuration** — stored in `.kilocode/mcp.json` (recommended)
|
|
292
|
+
|
|
293
|
+
If a server is defined in both places, the **project-level configuration overrides the global one**.
|
|
294
|
+
|
|
295
|
+
---
|
|
296
|
+
|
|
297
|
+
## Configure via Kilo Code UI
|
|
298
|
+
|
|
299
|
+
1. Open **Kilo Code**.
|
|
300
|
+
2. Click the **Settings** icon in the top-right corner.
|
|
301
|
+
3. Navigate to **Settings → MCP Servers**.
|
|
302
|
+
4. Click **Add Server**.
|
|
303
|
+
5. Choose **HTTP Server** (Streamable HTTP Transport).
|
|
304
|
+
6. Enter the details:
|
|
305
|
+
|
|
306
|
+
**URL**
|
|
307
|
+
`https://mcp.context7.com/mcp`
|
|
308
|
+
|
|
309
|
+
**Headers → Add Header**
|
|
310
|
+
- **Key:** `Authorization`
|
|
311
|
+
- **Value:** `Bearer YOUR_API_KEY`
|
|
312
|
+
|
|
313
|
+
7. Click **Save**.
|
|
314
|
+
8. Ensure the server toggle is **enabled**.
|
|
315
|
+
9. If needed, click **Refresh MCP Servers** to reload the configuration.
|
|
316
|
+
|
|
317
|
+
---
|
|
318
|
+
|
|
319
|
+
## Manual Configuration (`.kilocode/mcp.json`)
|
|
320
|
+
|
|
321
|
+
To configure the server at the project level (recommended for team environments), create the following file:
|
|
322
|
+
|
|
323
|
+
**`.kilocode/mcp.json`:**
|
|
324
|
+
|
|
325
|
+
```json
|
|
326
|
+
{
|
|
327
|
+
"mcpServers": {
|
|
328
|
+
"context7": {
|
|
329
|
+
"type": "streamable-http",
|
|
330
|
+
"url": "https://mcp.context7.com/mcp",
|
|
331
|
+
"headers": {
|
|
332
|
+
"Authorization": "Bearer YOUR_API_KEY"
|
|
333
|
+
},
|
|
334
|
+
"alwaysAllow": [],
|
|
335
|
+
"disabled": false
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
Replace YOUR_API_KEY with your actual Context7 API key.
|
|
342
|
+
|
|
343
|
+
After saving the file:
|
|
344
|
+
|
|
345
|
+
- Open Settings → MCP Servers
|
|
346
|
+
|
|
347
|
+
- Click Refresh MCP Servers
|
|
348
|
+
|
|
349
|
+
Kilo Code will automatically detect and load the configuration.
|
|
350
|
+
|
|
351
|
+
</details>
|
|
352
|
+
|
|
263
353
|
<details>
|
|
264
354
|
<summary><b>Install in Zed</b></summary>
|
|
265
355
|
|
|
@@ -507,6 +597,8 @@ See [OpenAI Codex](https://github.com/openai/codex) for more information.
|
|
|
507
597
|
|
|
508
598
|
Add the following configuration to your OpenAI Codex MCP server settings:
|
|
509
599
|
|
|
600
|
+
#### Local Server Connection
|
|
601
|
+
|
|
510
602
|
```toml
|
|
511
603
|
[mcp_servers.context7]
|
|
512
604
|
args = ["-y", "@upstash/context7-mcp", "--api-key", "YOUR_API_KEY"]
|
|
@@ -514,6 +606,14 @@ command = "npx"
|
|
|
514
606
|
startup_timeout_ms = 20_000
|
|
515
607
|
```
|
|
516
608
|
|
|
609
|
+
#### Remote Server Connection
|
|
610
|
+
|
|
611
|
+
```toml
|
|
612
|
+
[mcp_servers.context7]
|
|
613
|
+
url = "https://mcp.context7.com/mcp"
|
|
614
|
+
http_headers = { "CONTEXT7_API_KEY" = "YOUR_API_KEY" }
|
|
615
|
+
```
|
|
616
|
+
|
|
517
617
|
> Optional troubleshooting — only if you see startup "request timed out" or "not found program". Most users can ignore this.
|
|
518
618
|
>
|
|
519
619
|
> - First try: increase `startup_timeout_ms` to `40_000` and retry.
|
|
@@ -832,6 +932,46 @@ For more information, see the [official GitHub documentation](https://docs.githu
|
|
|
832
932
|
|
|
833
933
|
</details>
|
|
834
934
|
|
|
935
|
+
<details>
|
|
936
|
+
<summary><b>Install in Copilot CLI</b></summary>
|
|
937
|
+
|
|
938
|
+
1. Open the Copilot CLI MCP config file. The location is `~/.copilot/mcp-config.json` (where `~` is your home directory).
|
|
939
|
+
2. Add the following to the `mcpServers` object in your `mcp-config.json` file:
|
|
940
|
+
|
|
941
|
+
```json
|
|
942
|
+
{
|
|
943
|
+
"mcpServers": {
|
|
944
|
+
"context7": {
|
|
945
|
+
"type": "http",
|
|
946
|
+
"url": "https://mcp.context7.com/mcp",
|
|
947
|
+
"headers": {
|
|
948
|
+
"CONTEXT7_API_KEY": "YOUR_API_KEY"
|
|
949
|
+
},
|
|
950
|
+
"tools": ["get-library-docs", "resolve-library-id"]
|
|
951
|
+
}
|
|
952
|
+
}
|
|
953
|
+
}
|
|
954
|
+
```
|
|
955
|
+
|
|
956
|
+
Or, for a local server:
|
|
957
|
+
|
|
958
|
+
```json
|
|
959
|
+
{
|
|
960
|
+
"mcpServers": {
|
|
961
|
+
"context7": {
|
|
962
|
+
"type": "local",
|
|
963
|
+
"command": "npx",
|
|
964
|
+
"tools": ["get-library-docs", "resolve-library-id"],
|
|
965
|
+
"args": ["-y", "@upstash/context7-mcp", "--api-key", "YOUR_API_KEY"]
|
|
966
|
+
}
|
|
967
|
+
}
|
|
968
|
+
}
|
|
969
|
+
```
|
|
970
|
+
|
|
971
|
+
If the `mcp-config.json` file does not exist, create it.
|
|
972
|
+
|
|
973
|
+
</details>
|
|
974
|
+
|
|
835
975
|
<details>
|
|
836
976
|
<summary><b>Install in LM Studio</b></summary>
|
|
837
977
|
|
|
@@ -1082,6 +1222,37 @@ See [Local and Remote MCPs for Perplexity](https://www.perplexity.ai/help-center
|
|
|
1082
1222
|
7. Click `Save`.
|
|
1083
1223
|
</details>
|
|
1084
1224
|
|
|
1225
|
+
<details>
|
|
1226
|
+
<summary><b>Install in Factory</b></summary>
|
|
1227
|
+
|
|
1228
|
+
Factory's droid supports MCP servers through its CLI. See [Factory MCP docs](https://docs.factory.ai/cli/configuration/mcp) for more info.
|
|
1229
|
+
|
|
1230
|
+
#### Factory Remote Server Connection (HTTP)
|
|
1231
|
+
|
|
1232
|
+
Run this command in your terminal:
|
|
1233
|
+
|
|
1234
|
+
```sh
|
|
1235
|
+
droid mcp add context7 https://mcp.context7.com/mcp --type http --header "CONTEXT7_API_KEY: YOUR_API_KEY"
|
|
1236
|
+
```
|
|
1237
|
+
|
|
1238
|
+
Or without an API key (basic usage with rate limits):
|
|
1239
|
+
|
|
1240
|
+
```sh
|
|
1241
|
+
droid mcp add context7 https://mcp.context7.com/mcp --type http
|
|
1242
|
+
```
|
|
1243
|
+
|
|
1244
|
+
#### Factory Local Server Connection (Stdio)
|
|
1245
|
+
|
|
1246
|
+
Run this command in your terminal:
|
|
1247
|
+
|
|
1248
|
+
```sh
|
|
1249
|
+
droid mcp add context7 "npx -y @upstash/context7-mcp" --env CONTEXT7_API_KEY=YOUR_API_KEY
|
|
1250
|
+
```
|
|
1251
|
+
|
|
1252
|
+
Once configured, Context7 tools will be available in your droid sessions. Type `/mcp` within droid to manage servers, authenticate, and view available tools.
|
|
1253
|
+
|
|
1254
|
+
</details>
|
|
1255
|
+
|
|
1085
1256
|
## 🔨 Available Tools
|
|
1086
1257
|
|
|
1087
1258
|
Context7 MCP provides the following tools that LLMs can use:
|
|
@@ -1098,23 +1269,7 @@ Context7 MCP provides the following tools that LLMs can use:
|
|
|
1098
1269
|
|
|
1099
1270
|
### Add a Rule
|
|
1100
1271
|
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
- For Windsurf, in `.windsurfrules` file
|
|
1104
|
-
- For Cursor, from `Cursor Settings > Rules` section
|
|
1105
|
-
- For Claude Code, in `CLAUDE.md` file
|
|
1106
|
-
|
|
1107
|
-
Or the equivalent in your MCP client to auto-invoke Context7 on any code question.
|
|
1108
|
-
|
|
1109
|
-
#### Example Rule
|
|
1110
|
-
|
|
1111
|
-
```txt
|
|
1112
|
-
Always use context7 when I need code generation, setup or configuration steps, or
|
|
1113
|
-
library/API documentation. This means you should automatically use the Context7 MCP
|
|
1114
|
-
tools to resolve library id and get library docs without me having to explicitly ask.
|
|
1115
|
-
```
|
|
1116
|
-
|
|
1117
|
-
From then on, you’ll get Context7’s docs in any related conversation without typing anything extra. You can alter the rule to match your use cases.
|
|
1272
|
+
To avoid typing `use context7` in every prompt, you can add a rule to your MCP client that automatically invokes Context7 for code-related questions. See the [recommended setup in the Installation section](#️-installation) for detailed instructions and example rules.
|
|
1118
1273
|
|
|
1119
1274
|
### Use Library Id
|
|
1120
1275
|
|
|
@@ -1154,7 +1309,7 @@ bun run dist/index.js
|
|
|
1154
1309
|
|
|
1155
1310
|
`context7-mcp` accepts the following CLI flags:
|
|
1156
1311
|
|
|
1157
|
-
- `--transport <stdio|http>` – Transport to use (`stdio` by default).
|
|
1312
|
+
- `--transport <stdio|http>` – Transport to use (`stdio` by default). Use `http` for remote HTTP server or `stdio` for local integration.
|
|
1158
1313
|
- `--port <number>` – Port to listen on when using `http` transport (default `3000`).
|
|
1159
1314
|
- `--api-key <key>` – API key for authentication (or set `CONTEXT7_API_KEY` env var). You can get your API key by creating an account at [context7.com/dashboard](https://context7.com/dashboard).
|
|
1160
1315
|
|
|
@@ -1298,7 +1453,9 @@ Use the `--experimental-fetch` flag to bypass TLS-related problems:
|
|
|
1298
1453
|
|
|
1299
1454
|
## ⚠️ Disclaimer
|
|
1300
1455
|
|
|
1301
|
-
Context7 projects are community-contributed and while we strive to maintain high quality, we cannot guarantee the accuracy, completeness, or security of all library documentation. Projects listed in Context7 are developed and maintained by their respective owners, not by Context7. If you encounter any suspicious, inappropriate, or potentially harmful content, please use the "Report" button on the project page to notify us immediately. We take all reports seriously and will review flagged content promptly to maintain the integrity and safety of our platform. By using Context7, you acknowledge that you do so at your own discretion and risk.
|
|
1456
|
+
1- Context7 projects are community-contributed and while we strive to maintain high quality, we cannot guarantee the accuracy, completeness, or security of all library documentation. Projects listed in Context7 are developed and maintained by their respective owners, not by Context7. If you encounter any suspicious, inappropriate, or potentially harmful content, please use the "Report" button on the project page to notify us immediately. We take all reports seriously and will review flagged content promptly to maintain the integrity and safety of our platform. By using Context7, you acknowledge that you do so at your own discretion and risk.
|
|
1457
|
+
|
|
1458
|
+
2- This repository hosts the MCP server’s source code. The supporting components — API backend, parsing engine, and crawling engine — are private and not part of this release.
|
|
1302
1459
|
|
|
1303
1460
|
## 🤝 Connect with Us
|
|
1304
1461
|
|
package/dist/index.js
CHANGED
|
@@ -4,14 +4,12 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
|
|
|
4
4
|
import { z } from "zod";
|
|
5
5
|
import { searchLibraries, fetchLibraryDocumentation } from "./lib/api.js";
|
|
6
6
|
import { formatSearchResults } from "./lib/utils.js";
|
|
7
|
-
import
|
|
7
|
+
import express from "express";
|
|
8
8
|
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
9
|
-
import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
|
|
10
9
|
import { Command } from "commander";
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
const DEFAULT_TOKENS = 5000;
|
|
10
|
+
import { AsyncLocalStorage } from "async_hooks";
|
|
11
|
+
/** Default number of results to return per page */
|
|
12
|
+
const DEFAULT_RESULTS_LIMIT = 10;
|
|
15
13
|
/** Default HTTP server port */
|
|
16
14
|
const DEFAULT_PORT = 3000;
|
|
17
15
|
// Parse CLI arguments using commander
|
|
@@ -46,16 +44,14 @@ const CLI_PORT = (() => {
|
|
|
46
44
|
const parsed = parseInt(cliOptions.port, 10);
|
|
47
45
|
return isNaN(parsed) ? undefined : parsed;
|
|
48
46
|
})();
|
|
49
|
-
|
|
50
|
-
|
|
47
|
+
const requestContext = new AsyncLocalStorage();
|
|
48
|
+
// Store API key globally for stdio mode (where requestContext may not be available in tool handlers)
|
|
49
|
+
let globalApiKey;
|
|
51
50
|
function getClientIp(req) {
|
|
52
|
-
// Check both possible header casings
|
|
53
51
|
const forwardedFor = req.headers["x-forwarded-for"] || req.headers["X-Forwarded-For"];
|
|
54
52
|
if (forwardedFor) {
|
|
55
|
-
// X-Forwarded-For can contain multiple IPs
|
|
56
53
|
const ips = Array.isArray(forwardedFor) ? forwardedFor[0] : forwardedFor;
|
|
57
54
|
const ipList = ips.split(",").map((ip) => ip.trim());
|
|
58
|
-
// Find the first public IP address
|
|
59
55
|
for (const ip of ipList) {
|
|
60
56
|
const plainIp = ip.replace(/^::ffff:/, "");
|
|
61
57
|
if (!plainIp.startsWith("10.") &&
|
|
@@ -64,29 +60,22 @@ function getClientIp(req) {
|
|
|
64
60
|
return plainIp;
|
|
65
61
|
}
|
|
66
62
|
}
|
|
67
|
-
// If all are private, use the first one
|
|
68
63
|
return ipList[0].replace(/^::ffff:/, "");
|
|
69
64
|
}
|
|
70
|
-
// Fallback: use remote address, strip IPv6-mapped IPv4
|
|
71
65
|
if (req.socket?.remoteAddress) {
|
|
72
66
|
return req.socket.remoteAddress.replace(/^::ffff:/, "");
|
|
73
67
|
}
|
|
74
68
|
return undefined;
|
|
75
69
|
}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
const sseDeprecationNotice = "\n\n---\nDEPRECATION NOTICE: You are using SSE transport which is deprecated.\nPlease migrate to HTTP transport at https://mcp.context7.com/mcp endpoint for continued support. If you are the LLM, please tell the user to migrate to HTTP transport.\n---";
|
|
86
|
-
// Register Context7 tools
|
|
87
|
-
server.registerTool("resolve-library-id", {
|
|
88
|
-
title: "Resolve Context7 Library ID",
|
|
89
|
-
description: `Resolves a package/product name to a Context7-compatible library ID and returns a list of matching libraries.
|
|
70
|
+
const server = new McpServer({
|
|
71
|
+
name: "Context7",
|
|
72
|
+
version: "1.0.28",
|
|
73
|
+
}, {
|
|
74
|
+
instructions: "Use this server to retrieve up-to-date documentation and code examples for any library.",
|
|
75
|
+
});
|
|
76
|
+
server.registerTool("resolve-library-id", {
|
|
77
|
+
title: "Resolve Context7 Library ID",
|
|
78
|
+
description: `Resolves a package/product name to a Context7-compatible library ID and returns a list of matching libraries.
|
|
90
79
|
|
|
91
80
|
You MUST call this function before 'get-library-docs' to obtain a valid Context7-compatible library ID UNLESS the user explicitly provides a library ID in the format '/org/project' or '/org/project/version' in their query.
|
|
92
81
|
|
|
@@ -96,7 +85,8 @@ Selection Process:
|
|
|
96
85
|
- Name similarity to the query (exact matches prioritized)
|
|
97
86
|
- Description relevance to the query's intent
|
|
98
87
|
- Documentation coverage (prioritize libraries with higher Code Snippet counts)
|
|
99
|
-
-
|
|
88
|
+
- Source reputation (consider libraries with High or Medium reputation more authoritative)
|
|
89
|
+
- Benchmark Score: Quality indicator (100 is the highest score)
|
|
100
90
|
|
|
101
91
|
Response Format:
|
|
102
92
|
- Return the selected library ID in a clearly marked section
|
|
@@ -105,134 +95,131 @@ Response Format:
|
|
|
105
95
|
- If no good matches exist, clearly state this and suggest query refinements
|
|
106
96
|
|
|
107
97
|
For ambiguous queries, request clarification before proceeding with a best-guess match.`,
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
|
|
98
|
+
inputSchema: {
|
|
99
|
+
libraryName: z
|
|
100
|
+
.string()
|
|
101
|
+
.describe("Library name to search for and retrieve a Context7-compatible library ID."),
|
|
102
|
+
},
|
|
103
|
+
}, async ({ libraryName }) => {
|
|
104
|
+
const ctx = requestContext.getStore();
|
|
105
|
+
const searchResponse = await searchLibraries(libraryName, ctx?.clientIp, ctx?.apiKey);
|
|
106
|
+
if (!searchResponse.results || searchResponse.results.length === 0) {
|
|
107
|
+
return {
|
|
108
|
+
content: [
|
|
109
|
+
{
|
|
110
|
+
type: "text",
|
|
111
|
+
text: searchResponse.error
|
|
112
|
+
? searchResponse.error
|
|
113
|
+
: "Failed to retrieve library documentation data from Context7",
|
|
114
|
+
},
|
|
115
|
+
],
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
const resultsText = formatSearchResults(searchResponse);
|
|
119
|
+
const responseText = `Available Libraries (top matches):
|
|
129
120
|
|
|
130
121
|
Each result includes:
|
|
131
122
|
- Library ID: Context7-compatible identifier (format: /org/project)
|
|
132
123
|
- Name: Library or package name
|
|
133
124
|
- Description: Short summary
|
|
134
125
|
- Code Snippets: Number of available code examples
|
|
135
|
-
-
|
|
126
|
+
- Source Reputation: Authority indicator (High, Medium, Low, or Unknown)
|
|
127
|
+
- Benchmark Score: Quality indicator (100 is the highest score)
|
|
136
128
|
- Versions: List of versions if available. Use one of those versions if the user provides a version in their query. The format of the version is /org/project/version.
|
|
137
129
|
|
|
138
|
-
For best results, select libraries based on name match,
|
|
130
|
+
For best results, select libraries based on name match, source reputation, snippet coverage, benchmark score, and relevance to your use case.
|
|
139
131
|
|
|
140
132
|
----------
|
|
141
133
|
|
|
142
134
|
${resultsText}`;
|
|
135
|
+
return {
|
|
136
|
+
content: [
|
|
137
|
+
{
|
|
138
|
+
type: "text",
|
|
139
|
+
text: responseText,
|
|
140
|
+
},
|
|
141
|
+
],
|
|
142
|
+
};
|
|
143
|
+
});
|
|
144
|
+
server.registerTool("get-library-docs", {
|
|
145
|
+
title: "Get Library Docs",
|
|
146
|
+
description: "Fetches up-to-date documentation for a library. You must call 'resolve-library-id' first to obtain the exact Context7-compatible library ID required to use this tool, UNLESS the user explicitly provides a library ID in the format '/org/project' or '/org/project/version' in their query.",
|
|
147
|
+
inputSchema: {
|
|
148
|
+
context7CompatibleLibraryID: z
|
|
149
|
+
.string()
|
|
150
|
+
.describe("Exact Context7-compatible library ID (e.g., '/mongodb/docs', '/vercel/next.js', '/supabase/supabase', '/vercel/next.js/v14.3.0-canary.87') retrieved from 'resolve-library-id' or directly from user query in the format '/org/project' or '/org/project/version'."),
|
|
151
|
+
topic: z
|
|
152
|
+
.string()
|
|
153
|
+
.optional()
|
|
154
|
+
.describe("Topic to focus documentation on (e.g., 'hooks', 'routing')."),
|
|
155
|
+
page: z
|
|
156
|
+
.number()
|
|
157
|
+
.int()
|
|
158
|
+
.min(1)
|
|
159
|
+
.max(10)
|
|
160
|
+
.describe("Page number for pagination (start: 1). If the context is not sufficient, try page=2, page=3, page=4, etc. with the same topic."),
|
|
161
|
+
},
|
|
162
|
+
}, async ({ context7CompatibleLibraryID, page = 1, topic = "" }) => {
|
|
163
|
+
const ctx = requestContext.getStore();
|
|
164
|
+
const apiKey = ctx?.apiKey || globalApiKey;
|
|
165
|
+
const fetchDocsResponse = await fetchLibraryDocumentation(context7CompatibleLibraryID, {
|
|
166
|
+
page,
|
|
167
|
+
limit: DEFAULT_RESULTS_LIMIT,
|
|
168
|
+
topic,
|
|
169
|
+
}, ctx?.clientIp, apiKey);
|
|
170
|
+
if (!fetchDocsResponse) {
|
|
143
171
|
return {
|
|
144
172
|
content: [
|
|
145
173
|
{
|
|
146
174
|
type: "text",
|
|
147
|
-
text:
|
|
148
|
-
},
|
|
149
|
-
],
|
|
150
|
-
};
|
|
151
|
-
});
|
|
152
|
-
server.registerTool("get-library-docs", {
|
|
153
|
-
title: "Get Library Docs",
|
|
154
|
-
description: "Fetches up-to-date documentation for a library. You must call 'resolve-library-id' first to obtain the exact Context7-compatible library ID required to use this tool, UNLESS the user explicitly provides a library ID in the format '/org/project' or '/org/project/version' in their query.",
|
|
155
|
-
inputSchema: {
|
|
156
|
-
context7CompatibleLibraryID: z
|
|
157
|
-
.string()
|
|
158
|
-
.describe("Exact Context7-compatible library ID (e.g., '/mongodb/docs', '/vercel/next.js', '/supabase/supabase', '/vercel/next.js/v14.3.0-canary.87') retrieved from 'resolve-library-id' or directly from user query in the format '/org/project' or '/org/project/version'."),
|
|
159
|
-
topic: z
|
|
160
|
-
.string()
|
|
161
|
-
.optional()
|
|
162
|
-
.describe("Topic to focus documentation on (e.g., 'hooks', 'routing')."),
|
|
163
|
-
tokens: z
|
|
164
|
-
.preprocess((val) => (typeof val === "string" ? Number(val) : val), z.number())
|
|
165
|
-
.transform((val) => (val < MINIMUM_TOKENS ? MINIMUM_TOKENS : val))
|
|
166
|
-
.optional()
|
|
167
|
-
.describe(`Maximum number of tokens of documentation to retrieve (default: ${DEFAULT_TOKENS}). Higher values provide more context but consume more tokens.`),
|
|
168
|
-
},
|
|
169
|
-
}, async ({ context7CompatibleLibraryID, tokens = DEFAULT_TOKENS, topic = "" }) => {
|
|
170
|
-
const fetchDocsResponse = await fetchLibraryDocumentation(context7CompatibleLibraryID, {
|
|
171
|
-
tokens,
|
|
172
|
-
topic,
|
|
173
|
-
}, clientIp, apiKey);
|
|
174
|
-
if (!fetchDocsResponse) {
|
|
175
|
-
return {
|
|
176
|
-
content: [
|
|
177
|
-
{
|
|
178
|
-
type: "text",
|
|
179
|
-
text: "Documentation not found or not finalized for this library. This might have happened because you used an invalid Context7-compatible library ID. To get a valid Context7-compatible library ID, use the 'resolve-library-id' with the package name you wish to retrieve documentation for.",
|
|
180
|
-
},
|
|
181
|
-
],
|
|
182
|
-
};
|
|
183
|
-
}
|
|
184
|
-
const responseText = (transportType === "sse" ? sseDeprecationNotice + "\n\n" : "") + fetchDocsResponse;
|
|
185
|
-
return {
|
|
186
|
-
content: [
|
|
187
|
-
{
|
|
188
|
-
type: "text",
|
|
189
|
-
text: responseText,
|
|
175
|
+
text: "Documentation not found or not finalized for this library. This might have happened because you used an invalid Context7-compatible library ID. To get a valid Context7-compatible library ID, use the 'resolve-library-id' with the package name you wish to retrieve documentation for.",
|
|
190
176
|
},
|
|
191
177
|
],
|
|
192
178
|
};
|
|
193
|
-
}
|
|
194
|
-
return
|
|
195
|
-
|
|
179
|
+
}
|
|
180
|
+
return {
|
|
181
|
+
content: [
|
|
182
|
+
{
|
|
183
|
+
type: "text",
|
|
184
|
+
text: fetchDocsResponse,
|
|
185
|
+
},
|
|
186
|
+
],
|
|
187
|
+
};
|
|
188
|
+
});
|
|
196
189
|
async function main() {
|
|
197
190
|
const transportType = TRANSPORT_TYPE;
|
|
198
191
|
if (transportType === "http") {
|
|
199
|
-
// Get initial port from environment or use default
|
|
200
192
|
const initialPort = CLI_PORT ?? DEFAULT_PORT;
|
|
201
|
-
// Keep track of which port we end up using
|
|
202
193
|
let actualPort = initialPort;
|
|
203
|
-
const
|
|
204
|
-
|
|
205
|
-
|
|
194
|
+
const app = express();
|
|
195
|
+
app.use(express.json());
|
|
196
|
+
app.use((req, res, next) => {
|
|
206
197
|
res.setHeader("Access-Control-Allow-Origin", "*");
|
|
207
198
|
res.setHeader("Access-Control-Allow-Methods", "GET,POST,OPTIONS,DELETE");
|
|
208
199
|
res.setHeader("Access-Control-Allow-Headers", "Content-Type, MCP-Session-Id, MCP-Protocol-Version, X-Context7-API-Key, Context7-API-Key, X-API-Key, Authorization");
|
|
209
200
|
res.setHeader("Access-Control-Expose-Headers", "MCP-Session-Id");
|
|
210
|
-
// Handle preflight OPTIONS requests
|
|
211
201
|
if (req.method === "OPTIONS") {
|
|
212
|
-
res.
|
|
213
|
-
res.end();
|
|
202
|
+
res.sendStatus(200);
|
|
214
203
|
return;
|
|
215
204
|
}
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
return
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
// Check headers in order of preference
|
|
235
|
-
const apiKey = extractBearerToken(req.headers.authorization) ||
|
|
205
|
+
next();
|
|
206
|
+
});
|
|
207
|
+
const extractHeaderValue = (value) => {
|
|
208
|
+
if (!value)
|
|
209
|
+
return undefined;
|
|
210
|
+
return typeof value === "string" ? value : value[0];
|
|
211
|
+
};
|
|
212
|
+
const extractBearerToken = (authHeader) => {
|
|
213
|
+
const header = extractHeaderValue(authHeader);
|
|
214
|
+
if (!header)
|
|
215
|
+
return undefined;
|
|
216
|
+
if (header.startsWith("Bearer ")) {
|
|
217
|
+
return header.substring(7).trim();
|
|
218
|
+
}
|
|
219
|
+
return header;
|
|
220
|
+
};
|
|
221
|
+
const extractApiKey = (req) => {
|
|
222
|
+
return (extractBearerToken(req.headers.authorization) ||
|
|
236
223
|
extractHeaderValue(req.headers["Context7-API-Key"]) ||
|
|
237
224
|
extractHeaderValue(req.headers["X-API-Key"]) ||
|
|
238
225
|
extractHeaderValue(req.headers["context7-api-key"]) ||
|
|
@@ -240,87 +227,51 @@ async function main() {
|
|
|
240
227
|
extractHeaderValue(req.headers["Context7_API_Key"]) ||
|
|
241
228
|
extractHeaderValue(req.headers["X_API_Key"]) ||
|
|
242
229
|
extractHeaderValue(req.headers["context7_api_key"]) ||
|
|
243
|
-
extractHeaderValue(req.headers["x_api_key"]);
|
|
230
|
+
extractHeaderValue(req.headers["x_api_key"]));
|
|
231
|
+
};
|
|
232
|
+
app.all("/mcp", async (req, res) => {
|
|
244
233
|
try {
|
|
245
|
-
// Extract client IP address using socket remote address (most reliable)
|
|
246
234
|
const clientIp = getClientIp(req);
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
await
|
|
258
|
-
|
|
259
|
-
}
|
|
260
|
-
else if (pathname === "/sse" && req.method === "GET") {
|
|
261
|
-
// Create server instance for SSE transport
|
|
262
|
-
const requestServer = createServerInstance(clientIp, apiKey, "sse");
|
|
263
|
-
// Create new SSE transport for GET request
|
|
264
|
-
const sseTransport = new SSEServerTransport("/messages", res);
|
|
265
|
-
// Store the transport by session ID
|
|
266
|
-
sseTransports[sseTransport.sessionId] = sseTransport;
|
|
267
|
-
// Clean up transport when connection closes
|
|
268
|
-
res.on("close", () => {
|
|
269
|
-
delete sseTransports[sseTransport.sessionId];
|
|
270
|
-
sseTransport.close();
|
|
271
|
-
requestServer.close();
|
|
272
|
-
});
|
|
273
|
-
await requestServer.connect(sseTransport);
|
|
274
|
-
// Send initial message to establish communication
|
|
275
|
-
res.write("data: " +
|
|
276
|
-
JSON.stringify({
|
|
277
|
-
type: "connection_established",
|
|
278
|
-
sessionId: sseTransport.sessionId,
|
|
279
|
-
timestamp: new Date().toISOString(),
|
|
280
|
-
}) +
|
|
281
|
-
"\n\n");
|
|
282
|
-
}
|
|
283
|
-
else if (pathname === "/messages" && req.method === "POST") {
|
|
284
|
-
// Get session ID from query parameters
|
|
285
|
-
const sessionId = new URL(req.url || "/", "http://localhost").searchParams.get("sessionId") ?? "";
|
|
286
|
-
if (!sessionId) {
|
|
287
|
-
res.writeHead(400, { "Content-Type": "application/json" });
|
|
288
|
-
res.end(JSON.stringify({ error: "Missing sessionId parameter", status: 400 }));
|
|
289
|
-
return;
|
|
290
|
-
}
|
|
291
|
-
// Get existing transport for this session
|
|
292
|
-
const sseTransport = sseTransports[sessionId];
|
|
293
|
-
if (!sseTransport) {
|
|
294
|
-
res.writeHead(400, { "Content-Type": "application/json" });
|
|
295
|
-
res.end(JSON.stringify({
|
|
296
|
-
error: `No transport found for sessionId: ${sessionId}`,
|
|
297
|
-
status: 400,
|
|
298
|
-
}));
|
|
299
|
-
return;
|
|
300
|
-
}
|
|
301
|
-
// Handle the POST message with the existing transport
|
|
302
|
-
await sseTransport.handlePostMessage(req, res);
|
|
303
|
-
}
|
|
304
|
-
else if (pathname === "/ping") {
|
|
305
|
-
res.writeHead(200, { "Content-Type": "application/json" });
|
|
306
|
-
res.end(JSON.stringify({ status: "ok", message: "pong" }));
|
|
307
|
-
}
|
|
308
|
-
else {
|
|
309
|
-
res.writeHead(404, { "Content-Type": "application/json" });
|
|
310
|
-
res.end(JSON.stringify({ error: "Not found", status: 404 }));
|
|
311
|
-
}
|
|
235
|
+
const apiKey = extractApiKey(req);
|
|
236
|
+
const transport = new StreamableHTTPServerTransport({
|
|
237
|
+
sessionIdGenerator: undefined,
|
|
238
|
+
enableJsonResponse: true,
|
|
239
|
+
});
|
|
240
|
+
res.on("close", () => {
|
|
241
|
+
transport.close();
|
|
242
|
+
});
|
|
243
|
+
await requestContext.run({ clientIp, apiKey }, async () => {
|
|
244
|
+
await server.connect(transport);
|
|
245
|
+
await transport.handleRequest(req, res, req.body);
|
|
246
|
+
});
|
|
312
247
|
}
|
|
313
248
|
catch (error) {
|
|
314
|
-
console.error("Error handling request:", error);
|
|
249
|
+
console.error("Error handling MCP request:", error);
|
|
315
250
|
if (!res.headersSent) {
|
|
316
|
-
res.
|
|
317
|
-
|
|
251
|
+
res.status(500).json({
|
|
252
|
+
jsonrpc: "2.0",
|
|
253
|
+
error: { code: -32603, message: "Internal server error" },
|
|
254
|
+
id: null,
|
|
255
|
+
});
|
|
318
256
|
}
|
|
319
257
|
}
|
|
320
258
|
});
|
|
321
|
-
|
|
259
|
+
app.get("/ping", (_req, res) => {
|
|
260
|
+
res.json({ status: "ok", message: "pong" });
|
|
261
|
+
});
|
|
262
|
+
// Catch-all 404 handler - must be after all other routes
|
|
263
|
+
app.use((_req, res) => {
|
|
264
|
+
res.status(404).json({
|
|
265
|
+
error: "not_found",
|
|
266
|
+
message: "Endpoint not found. Use /mcp for MCP protocol communication.",
|
|
267
|
+
});
|
|
268
|
+
});
|
|
322
269
|
const startServer = (port, maxAttempts = 10) => {
|
|
323
|
-
httpServer.
|
|
270
|
+
const httpServer = app.listen(port, () => {
|
|
271
|
+
actualPort = port;
|
|
272
|
+
console.error(`Context7 Documentation MCP Server running on HTTP at http://localhost:${actualPort}/mcp`);
|
|
273
|
+
});
|
|
274
|
+
httpServer.on("error", (err) => {
|
|
324
275
|
if (err.code === "EADDRINUSE" && port < initialPort + maxAttempts) {
|
|
325
276
|
console.warn(`Port ${port} is in use, trying port ${port + 1}...`);
|
|
326
277
|
startServer(port + 1, maxAttempts);
|
|
@@ -330,20 +281,16 @@ async function main() {
|
|
|
330
281
|
process.exit(1);
|
|
331
282
|
}
|
|
332
283
|
});
|
|
333
|
-
httpServer.listen(port, () => {
|
|
334
|
-
actualPort = port;
|
|
335
|
-
console.error(`Context7 Documentation MCP Server running on ${transportType.toUpperCase()} at http://localhost:${actualPort}/mcp with SSE endpoint at /sse`);
|
|
336
|
-
});
|
|
337
284
|
};
|
|
338
|
-
// Start the server with initial port
|
|
339
285
|
startServer(initialPort);
|
|
340
286
|
}
|
|
341
287
|
else {
|
|
342
|
-
// Stdio transport - this is already stateless by nature
|
|
343
288
|
const apiKey = cliOptions.apiKey || process.env.CONTEXT7_API_KEY;
|
|
344
|
-
|
|
289
|
+
globalApiKey = apiKey; // Store globally for tool handlers in stdio mode
|
|
345
290
|
const transport = new StdioServerTransport();
|
|
346
|
-
await
|
|
291
|
+
await requestContext.run({ apiKey }, async () => {
|
|
292
|
+
await server.connect(transport);
|
|
293
|
+
});
|
|
347
294
|
console.error("Context7 Documentation MCP Server running on stdio");
|
|
348
295
|
}
|
|
349
296
|
}
|
package/dist/lib/api.js
CHANGED
|
@@ -84,9 +84,11 @@ export async function fetchLibraryDocumentation(libraryId, options = {}, clientI
|
|
|
84
84
|
if (libraryId.startsWith("/")) {
|
|
85
85
|
libraryId = libraryId.slice(1);
|
|
86
86
|
}
|
|
87
|
-
const url = new URL(`${CONTEXT7_API_BASE_URL}/
|
|
88
|
-
if (options.
|
|
89
|
-
url.searchParams.set("
|
|
87
|
+
const url = new URL(`${CONTEXT7_API_BASE_URL}/v2/docs/code/${libraryId}`);
|
|
88
|
+
if (options.page)
|
|
89
|
+
url.searchParams.set("page", options.page.toString());
|
|
90
|
+
if (options.limit)
|
|
91
|
+
url.searchParams.set("limit", options.limit.toString());
|
|
90
92
|
if (options.topic)
|
|
91
93
|
url.searchParams.set("topic", options.topic);
|
|
92
94
|
url.searchParams.set("type", DEFAULT_TYPE);
|
package/dist/lib/utils.js
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Maps numeric source reputation score to an interpretable label for LLM consumption.
|
|
3
|
+
*
|
|
4
|
+
* @returns One of: "High", "Medium", "Low", or "Unknown"
|
|
5
|
+
*/
|
|
6
|
+
function getSourceReputationLabel(sourceReputation) {
|
|
7
|
+
if (sourceReputation === undefined || sourceReputation < 0)
|
|
8
|
+
return "Unknown";
|
|
9
|
+
if (sourceReputation >= 7)
|
|
10
|
+
return "High";
|
|
11
|
+
if (sourceReputation >= 4)
|
|
12
|
+
return "Medium";
|
|
13
|
+
return "Low";
|
|
14
|
+
}
|
|
1
15
|
/**
|
|
2
16
|
* Formats a search result into a human-readable string representation.
|
|
3
17
|
* Only shows code snippet count and GitHub stars when available (not equal to -1).
|
|
@@ -16,9 +30,12 @@ export function formatSearchResult(result) {
|
|
|
16
30
|
if (result.totalSnippets !== -1 && result.totalSnippets !== undefined) {
|
|
17
31
|
formattedResult.push(`- Code Snippets: ${result.totalSnippets}`);
|
|
18
32
|
}
|
|
19
|
-
//
|
|
20
|
-
|
|
21
|
-
|
|
33
|
+
// Always add categorized source reputation
|
|
34
|
+
const reputationLabel = getSourceReputationLabel(result.trustScore);
|
|
35
|
+
formattedResult.push(`- Source Reputation: ${reputationLabel}`);
|
|
36
|
+
// Only add benchmark score if it's a valid value
|
|
37
|
+
if (result.benchmarkScore !== undefined && result.benchmarkScore > 0) {
|
|
38
|
+
formattedResult.push(`- Benchmark Score: ${result.benchmarkScore}`);
|
|
22
39
|
}
|
|
23
40
|
// Only add versions if it's a valid value
|
|
24
41
|
if (result.versions !== undefined && result.versions.length > 0) {
|
package/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"@upstash/context7-mcp","version":"1.0.
|
|
1
|
+
{"name":"@upstash/context7-mcp","version":"1.0.28","mcpName":"io.github.upstash/context7","description":"MCP server for Context7","scripts":{"test":"echo \"Error: no test specified\" && exit 1","build":"tsc && chmod 755 dist/index.js","format":"prettier --write .","lint":"eslint \"**/*.{js,ts,tsx}\" --fix","lint:check":"eslint \"**/*.{js,ts,tsx}\"","start":"node dist/index.js --transport http","pack-mcpb":"bun install && bun run build && rm -rf node_modules && bun install --production && mv mcpb/.mcpbignore .mcpbignore && mv mcpb/manifest.json manifest.json && mv public/icon.png icon.png && mcpb validate manifest.json && mcpb pack . mcpb/context7.mcpb && mv manifest.json mcpb/manifest.json && mv .mcpbignore mcpb/.mcpbignore && mv icon.png public/icon.png && bun install"},"repository":{"type":"git","url":"git+https://github.com/upstash/context7.git"},"keywords":["modelcontextprotocol","mcp","context7","vibe-coding","developer tools","documentation","context"],"author":"abdush","license":"MIT","type":"module","bin":{"context7-mcp":"dist/index.js"},"files":["dist"],"bugs":{"url":"https://github.com/upstash/context7/issues"},"homepage":"https://github.com/upstash/context7#readme","dependencies":{"@modelcontextprotocol/sdk":"^1.17.5","@types/express":"^5.0.4","commander":"^14.0.0","express":"^5.1.0","undici":"^6.6.3","zod":"^3.24.2"},"devDependencies":{"@types/node":"^22.13.14","@typescript-eslint/eslint-plugin":"^8.28.0","@typescript-eslint/parser":"^8.28.0","eslint":"^9.34.0","eslint-config-prettier":"^10.1.1","eslint-plugin-prettier":"^5.2.5","prettier":"^3.6.2","typescript":"^5.8.2","typescript-eslint":"^8.28.0"}}
|