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-03-31 15:19:29 +03:00
} ,
2025-04-17 01:03:45 +03:00
async ( { context7CompatibleLibraryID , tokens = DEFAULT_MINIMUM_TOKENS , topic = "" } ) = > {
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-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 ) ;
} ) ;