2025-04-03 12:32:03 +03:00
# ! / u s r / b i n / e n v n o d e
2025-03-31 15:19:29 +03:00
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js" ;
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js" ;
import { z } from "zod" ;
2025-04-17 01:03:45 +03:00
import { searchLibraries , fetchLibraryDocumentation } from "./lib/api.js" ;
import { formatSearchResults } from "./lib/utils.js" ;
2025-05-01 20:27:03 +07:00
import dotenv from "dotenv" ;
2025-04-17 01:03:45 +03:00
2025-05-01 20:27:03 +07:00
// Load environment variables from .env file if present
dotenv . config ( ) ;
// Get DEFAULT_MINIMUM_TOKENS from environment variable or use default
2025-05-01 22:50:40 +03:00
let DEFAULT_MINIMUM_TOKENS = 10000 ;
2025-05-01 20:27:03 +07:00
if ( process . env . DEFAULT_MINIMUM_TOKENS ) {
const parsedValue = parseInt ( process . env . DEFAULT_MINIMUM_TOKENS , 10 ) ;
if ( ! isNaN ( parsedValue ) && parsedValue > 0 ) {
DEFAULT_MINIMUM_TOKENS = parsedValue ;
} else {
2025-05-01 22:50:40 +03:00
console . warn (
` Warning: Invalid DEFAULT_MINIMUM_TOKENS value provided in environment variable. Using default value of 10000 `
2025-05-01 20:27:03 +07:00
) ;
}
}
2025-03-31 15:19:29 +03:00
// Create server instance
const server = new McpServer ( {
2025-04-03 11:51:17 +03:00
name : "Context7" ,
2025-04-11 15:10:59 +02:00
description : "Retrieves up-to-date documentation and code examples for any library." ,
2025-04-23 20:02:53 +03:00
version : "1.0.6" ,
2025-03-31 15:19:29 +03:00
capabilities : {
resources : { } ,
tools : { } ,
} ,
} ) ;
2025-04-03 11:51:17 +03:00
// Register Context7 tools
2025-03-31 15:19:29 +03:00
server . tool (
2025-04-11 10:01:28 +02:00
"resolve-library-id" ,
2025-05-17 02:49:46 +03:00
` Resolves a package/product name to a Context7-compatible library ID and returns a list of matching libraries.
2025-05-02 00:09:19 +03:00
2025-05-24 17:57:46 +03:00
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 .
2025-05-02 00:09:19 +03:00
2025-05-17 02:49:46 +03:00
Selection Process :
1 . Analyze the query to understand what library / package the user is looking for
2 . Return the most relevant match based on :
- Name similarity to the query ( exact matches prioritized )
- Description relevance to the query ' s intent
- Documentation coverage ( prioritize libraries with higher Code Snippet counts )
- Trust score ( consider libraries with scores of 7 - 10 more authoritative )
Response Format :
- Return the selected library ID in a clearly marked section
- Provide a brief explanation for why this library was chosen
- If multiple good matches exist , acknowledge this but proceed with the most relevant one
- If no good matches exist , clearly state this and suggest query refinements
For ambiguous queries , request clarification before proceeding with a best - guess match . ` ,
2025-04-04 20:29:10 +03:00
{
libraryName : z
. string ( )
2025-04-19 14:50:49 +03:00
. describe ( "Library name to search for and retrieve a Context7-compatible library ID." ) ,
2025-04-04 20:29:10 +03:00
} ,
async ( { libraryName } ) = > {
2025-04-19 14:50:49 +03:00
const searchResponse = await searchLibraries ( libraryName ) ;
2025-03-31 15:19:29 +03:00
2025-04-17 01:03:45 +03:00
if ( ! searchResponse || ! searchResponse . results ) {
2025-03-31 15:19:29 +03:00
return {
content : [
{
type : "text" ,
2025-04-04 18:20:07 +03:00
text : "Failed to retrieve library documentation data from Context7" ,
2025-03-31 15:19:29 +03:00
} ,
] ,
} ;
}
2025-04-17 01:03:45 +03:00
if ( searchResponse . results . length === 0 ) {
2025-03-31 15:19:29 +03:00
return {
content : [
{
type : "text" ,
2025-04-17 01:03:45 +03:00
text : "No documentation libraries available" ,
2025-03-31 15:19:29 +03:00
} ,
] ,
} ;
}
2025-04-17 01:03:45 +03:00
const resultsText = formatSearchResults ( searchResponse ) ;
2025-03-31 15:19:29 +03:00
return {
content : [
{
type : "text" ,
2025-05-02 00:09:19 +03:00
text : ` Available Libraries (top matches):
Each result includes :
2025-05-24 17:57:46 +03:00
- Library ID : Context7 - compatible identifier ( format : / o r g / p r o j e c t )
2025-05-02 00:09:19 +03:00
- Name : Library or package name
- Description : Short summary
- Code Snippets : Number of available code examples
2025-05-17 02:49:46 +03:00
- Trust Score : Authority indicator
2025-05-22 11:41:03 -07:00
- Versions : List of versions if available . Use one of those versions if and only if the user explicitly provides a version in their query .
2025-05-02 00:09:19 +03:00
2025-05-17 02:49:46 +03:00
For best results , select libraries based on name match , trust score , snippet coverage , and relevance to your use case .
2025-05-02 00:09:19 +03:00
2025-05-17 02:49:46 +03:00
-- -- -- -- --
2025-05-02 00:09:19 +03:00
$ { resultsText } ` ,
2025-03-31 15:19:29 +03:00
} ,
] ,
} ;
}
) ;
server . tool (
2025-04-11 10:01:28 +02:00
"get-library-docs" ,
2025-05-24 17:57:46 +03:00
"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." ,
2025-03-31 15:19:29 +03:00
{
2025-04-11 10:01:28 +02:00
context7CompatibleLibraryID : z
2025-04-03 11:51:17 +03:00
. string ( )
. describe (
2025-05-24 17:57:46 +03:00
"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'."
2025-04-03 11:51:17 +03:00
) ,
topic : z
. string ( )
2025-04-04 18:20:07 +03:00
. optional ( )
2025-04-11 10:01:28 +02:00
. describe ( "Topic to focus documentation on (e.g., 'hooks', 'routing')." ) ,
2025-04-03 11:51:17 +03:00
tokens : z
2025-04-19 16:14:24 +03:00
. preprocess ( ( val ) = > ( typeof val === "string" ? Number ( val ) : val ) , z . number ( ) )
2025-04-23 00:18:15 +03:00
. transform ( ( val ) = > ( val < DEFAULT_MINIMUM_TOKENS ? DEFAULT_MINIMUM_TOKENS : val ) )
2025-04-03 11:51:17 +03:00
. optional ( )
. describe (
2025-04-17 01:03:45 +03:00
` Maximum number of tokens of documentation to retrieve (default: ${ DEFAULT_MINIMUM_TOKENS } ). Higher values provide more context but consume more tokens. `
2025-04-03 11:51:17 +03:00
) ,
2025-05-24 19:33:15 +03:00
userQuery : z
. string ( )
. describe (
"Initial user query that triggered this tool call. Provide the user query as it is. Do not modify it or change it in any way. Do not add any additional information to the query."
) ,
2025-03-31 15:19:29 +03:00
} ,
2025-05-24 19:33:15 +03:00
async ( {
context7CompatibleLibraryID ,
tokens = DEFAULT_MINIMUM_TOKENS ,
topic = "" ,
userQuery ,
} ) = > {
2025-05-24 17:59:10 +03:00
const documentationText = await fetchLibraryDocumentation ( context7CompatibleLibraryID , {
2025-04-11 10:01:28 +02:00
tokens ,
2025-04-17 01:03:45 +03:00
topic ,
2025-05-24 19:33:15 +03:00
userQuery ,
2025-04-17 01:03:45 +03:00
} ) ;
2025-03-31 15:19:29 +03:00
2025-04-03 11:51:17 +03:00
if ( ! documentationText ) {
2025-03-31 15:19:29 +03:00
return {
content : [
{
type : "text" ,
2025-04-11 10:01:28 +02:00
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." ,
2025-03-31 15:19:29 +03:00
} ,
] ,
} ;
}
2025-04-03 11:51:17 +03:00
return {
content : [
{
type : "text" ,
text : documentationText ,
} ,
] ,
} ;
2025-03-31 15:19:29 +03:00
}
) ;
async function main() {
const transport = new StdioServerTransport ( ) ;
await server . connect ( transport ) ;
2025-04-03 11:51:17 +03:00
console . error ( "Context7 Documentation MCP Server running on stdio" ) ;
2025-03-31 15:19:29 +03:00
}
main ( ) . catch ( ( error ) = > {
console . error ( "Fatal error in main():" , error ) ;
process . exit ( 1 ) ;
} ) ;