@upstash/context7-mcp 1.0.2 → 1.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +19 -3
- package/dist/index.js +110 -0
- package/dist/lib/api.js +62 -0
- package/dist/lib/types.js +1 -0
- package/dist/lib/utils.js +20 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -52,7 +52,7 @@ Paste this into your Cursor `~/.cursor/mcp.json` file. See [Cursor MCP docs](htt
|
|
|
52
52
|
"mcpServers": {
|
|
53
53
|
"context7": {
|
|
54
54
|
"command": "npx",
|
|
55
|
-
"args": ["-y", "@upstash/context7-mcp"]
|
|
55
|
+
"args": ["-y", "@upstash/context7-mcp@latest"]
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
58
|
}
|
|
@@ -67,7 +67,23 @@ Add this to your Windsurf MCP config file. See [Windsurf MCP docs](https://docs.
|
|
|
67
67
|
"mcpServers": {
|
|
68
68
|
"context7": {
|
|
69
69
|
"command": "npx",
|
|
70
|
-
"args": ["-y", "@upstash/context7-mcp"]
|
|
70
|
+
"args": ["-y", "@upstash/context7-mcp@latest"]
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### Install in VSCode
|
|
77
|
+
|
|
78
|
+
Add this to your VSCode MCP config file. See [VSCode MCP docs](https://code.visualstudio.com/docs/copilot/chat/mcp-servers) for more info.
|
|
79
|
+
|
|
80
|
+
```json
|
|
81
|
+
{
|
|
82
|
+
"servers": {
|
|
83
|
+
"Context7": {
|
|
84
|
+
"type": "stdio",
|
|
85
|
+
"command": "npx",
|
|
86
|
+
"args": ["-y", "@upstash/context7-mcp@latest"]
|
|
71
87
|
}
|
|
72
88
|
}
|
|
73
89
|
}
|
|
@@ -112,7 +128,7 @@ bun run build
|
|
|
112
128
|
### Testing with MCP Inspector
|
|
113
129
|
|
|
114
130
|
```bash
|
|
115
|
-
npx -y @modelcontextprotocol/inspector npx @upstash/context7-mcp
|
|
131
|
+
npx -y @modelcontextprotocol/inspector npx @upstash/context7-mcp@latest
|
|
116
132
|
```
|
|
117
133
|
|
|
118
134
|
## License
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
import { searchLibraries, fetchLibraryDocumentation } from "./lib/api.js";
|
|
6
|
+
import { formatSearchResults } from "./lib/utils.js";
|
|
7
|
+
const DEFAULT_MINIMUM_TOKENS = 5000;
|
|
8
|
+
// Create server instance
|
|
9
|
+
const server = new McpServer({
|
|
10
|
+
name: "Context7",
|
|
11
|
+
description: "Retrieves up-to-date documentation and code examples for any library.",
|
|
12
|
+
version: "1.0.4",
|
|
13
|
+
capabilities: {
|
|
14
|
+
resources: {},
|
|
15
|
+
tools: {},
|
|
16
|
+
},
|
|
17
|
+
});
|
|
18
|
+
// Register Context7 tools
|
|
19
|
+
server.tool("resolve-library-id", "Required first step: Resolves a general package name into a Context7-compatible library ID. Must be called before using 'get-library-docs' to retrieve a valid Context7-compatible library ID.", {
|
|
20
|
+
libraryName: z
|
|
21
|
+
.string()
|
|
22
|
+
.optional()
|
|
23
|
+
.describe("Optional library name to search for and rerank results based on."),
|
|
24
|
+
}, async ({ libraryName }) => {
|
|
25
|
+
const searchResponse = await searchLibraries(libraryName || "");
|
|
26
|
+
if (!searchResponse || !searchResponse.results) {
|
|
27
|
+
return {
|
|
28
|
+
content: [
|
|
29
|
+
{
|
|
30
|
+
type: "text",
|
|
31
|
+
text: "Failed to retrieve library documentation data from Context7",
|
|
32
|
+
},
|
|
33
|
+
],
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
if (searchResponse.results.length === 0) {
|
|
37
|
+
return {
|
|
38
|
+
content: [
|
|
39
|
+
{
|
|
40
|
+
type: "text",
|
|
41
|
+
text: "No documentation libraries available",
|
|
42
|
+
},
|
|
43
|
+
],
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
const resultsText = formatSearchResults(searchResponse);
|
|
47
|
+
return {
|
|
48
|
+
content: [
|
|
49
|
+
{
|
|
50
|
+
type: "text",
|
|
51
|
+
text: "Available libraries and their Context7-compatible library IDs:\n\n" + resultsText,
|
|
52
|
+
},
|
|
53
|
+
],
|
|
54
|
+
};
|
|
55
|
+
});
|
|
56
|
+
server.tool("get-library-docs", "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.", {
|
|
57
|
+
context7CompatibleLibraryID: z
|
|
58
|
+
.string()
|
|
59
|
+
.describe("Exact Context7-compatible library ID (e.g., 'mongodb/docs', 'vercel/nextjs') retrieved from 'resolve-library-id'."),
|
|
60
|
+
topic: z
|
|
61
|
+
.string()
|
|
62
|
+
.optional()
|
|
63
|
+
.describe("Topic to focus documentation on (e.g., 'hooks', 'routing')."),
|
|
64
|
+
tokens: z
|
|
65
|
+
.number()
|
|
66
|
+
.min(DEFAULT_MINIMUM_TOKENS)
|
|
67
|
+
.optional()
|
|
68
|
+
.describe(`Maximum number of tokens of documentation to retrieve (default: ${DEFAULT_MINIMUM_TOKENS}). Higher values provide more context but consume more tokens.`),
|
|
69
|
+
}, async ({ context7CompatibleLibraryID, tokens = DEFAULT_MINIMUM_TOKENS, topic = "" }) => {
|
|
70
|
+
// Extract folders parameter if present in the ID
|
|
71
|
+
let folders = "";
|
|
72
|
+
let libraryId = context7CompatibleLibraryID;
|
|
73
|
+
if (context7CompatibleLibraryID.includes("?folders=")) {
|
|
74
|
+
const [id, foldersParam] = context7CompatibleLibraryID.split("?folders=");
|
|
75
|
+
libraryId = id;
|
|
76
|
+
folders = foldersParam;
|
|
77
|
+
}
|
|
78
|
+
const documentationText = await fetchLibraryDocumentation(libraryId, {
|
|
79
|
+
tokens,
|
|
80
|
+
topic,
|
|
81
|
+
folders,
|
|
82
|
+
});
|
|
83
|
+
if (!documentationText) {
|
|
84
|
+
return {
|
|
85
|
+
content: [
|
|
86
|
+
{
|
|
87
|
+
type: "text",
|
|
88
|
+
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.",
|
|
89
|
+
},
|
|
90
|
+
],
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
return {
|
|
94
|
+
content: [
|
|
95
|
+
{
|
|
96
|
+
type: "text",
|
|
97
|
+
text: documentationText,
|
|
98
|
+
},
|
|
99
|
+
],
|
|
100
|
+
};
|
|
101
|
+
});
|
|
102
|
+
async function main() {
|
|
103
|
+
const transport = new StdioServerTransport();
|
|
104
|
+
await server.connect(transport);
|
|
105
|
+
console.error("Context7 Documentation MCP Server running on stdio");
|
|
106
|
+
}
|
|
107
|
+
main().catch((error) => {
|
|
108
|
+
console.error("Fatal error in main():", error);
|
|
109
|
+
process.exit(1);
|
|
110
|
+
});
|
package/dist/lib/api.js
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
const CONTEXT7_API_BASE_URL = "https://context7.com/api";
|
|
2
|
+
const DEFAULT_TYPE = "txt";
|
|
3
|
+
/**
|
|
4
|
+
* Searches for libraries matching the given query
|
|
5
|
+
* @param query The search query
|
|
6
|
+
* @returns Search results or null if the request fails
|
|
7
|
+
*/
|
|
8
|
+
export async function searchLibraries(query) {
|
|
9
|
+
try {
|
|
10
|
+
const url = new URL(`${CONTEXT7_API_BASE_URL}/v1/search`);
|
|
11
|
+
url.searchParams.set("query", query);
|
|
12
|
+
const response = await fetch(url);
|
|
13
|
+
if (!response.ok) {
|
|
14
|
+
console.error(`Failed to search libraries: ${response.status}`);
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
return await response.json();
|
|
18
|
+
}
|
|
19
|
+
catch (error) {
|
|
20
|
+
console.error("Error searching libraries:", error);
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Fetches documentation context for a specific library
|
|
26
|
+
* @param libraryId The library ID to fetch documentation for
|
|
27
|
+
* @param options Options for the request
|
|
28
|
+
* @returns The documentation text or null if the request fails
|
|
29
|
+
*/
|
|
30
|
+
export async function fetchLibraryDocumentation(libraryId, options = {}) {
|
|
31
|
+
try {
|
|
32
|
+
if (libraryId.startsWith("/")) {
|
|
33
|
+
libraryId = libraryId.slice(1);
|
|
34
|
+
}
|
|
35
|
+
const url = new URL(`${CONTEXT7_API_BASE_URL}/v1/${libraryId}`);
|
|
36
|
+
if (options.tokens)
|
|
37
|
+
url.searchParams.set("tokens", options.tokens.toString());
|
|
38
|
+
if (options.topic)
|
|
39
|
+
url.searchParams.set("topic", options.topic);
|
|
40
|
+
if (options.folders)
|
|
41
|
+
url.searchParams.set("folders", options.folders);
|
|
42
|
+
url.searchParams.set("type", DEFAULT_TYPE);
|
|
43
|
+
const response = await fetch(url, {
|
|
44
|
+
headers: {
|
|
45
|
+
"X-Context7-Source": "mcp-server",
|
|
46
|
+
},
|
|
47
|
+
});
|
|
48
|
+
if (!response.ok) {
|
|
49
|
+
console.error(`Failed to fetch documentation: ${response.status}`);
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
const text = await response.text();
|
|
53
|
+
if (!text || text === "No content available" || text === "No context data available") {
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
return text;
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
console.error("Error fetching library documentation:", error);
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Format a search result into a string representation
|
|
3
|
+
* @param result SearchResult to format
|
|
4
|
+
* @returns Formatted search result string
|
|
5
|
+
*/
|
|
6
|
+
export function formatSearchResult(result) {
|
|
7
|
+
return `Title: ${result.title}\n\nContext7-compatible library ID: ${result.id}`;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Format search results into a string representation
|
|
11
|
+
* @param searchResponse The search response to format
|
|
12
|
+
* @returns Formatted search results string
|
|
13
|
+
*/
|
|
14
|
+
export function formatSearchResults(searchResponse) {
|
|
15
|
+
if (!searchResponse.results || searchResponse.results.length === 0) {
|
|
16
|
+
return "No documentation libraries found matching your query.";
|
|
17
|
+
}
|
|
18
|
+
const formattedResults = searchResponse.results.map(formatSearchResult);
|
|
19
|
+
return formattedResults.join("\n\n");
|
|
20
|
+
}
|