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-03 11:51:17 +03:00
import { fetchProjects , fetchPackageDocumentation } from "./lib/api.js" ;
import { formatProjectsList } from "./lib/utils.js" ;
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" ,
description : "Retrieves documentation for packages." ,
2025-03-31 15:19:29 +03:00
version : "1.0.0" ,
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-03 11:51:17 +03:00
"list-available-packages" ,
"Lists all packages from Context7. The package names can be used with 'get-package-documentation' to retrieve documentation." ,
2025-03-31 15:19:29 +03:00
async ( ) = > {
2025-04-03 11:51:17 +03:00
const projects = await fetchProjects ( ) ;
2025-03-31 15:19:29 +03:00
2025-04-03 11:51:17 +03:00
if ( ! projects ) {
2025-03-31 15:19:29 +03:00
return {
content : [
{
type : "text" ,
2025-04-03 11:51:17 +03:00
text : "Failed to retrieve packages data from Context7" ,
2025-03-31 15:19:29 +03:00
} ,
] ,
} ;
}
2025-04-03 11:51:17 +03:00
// Filter projects to only include those with state "finalized"
const finalizedProjects = projects . filter ( ( project ) = > project . version . state === "finalized" ) ;
if ( finalizedProjects . length === 0 ) {
2025-03-31 15:19:29 +03:00
return {
content : [
{
type : "text" ,
2025-04-03 11:51:17 +03:00
text : "No finalized documentation packages available" ,
2025-03-31 15:19:29 +03:00
} ,
] ,
} ;
}
2025-04-03 11:51:17 +03:00
const projectsText = formatProjectsList ( finalizedProjects ) ;
2025-03-31 15:19:29 +03:00
return {
content : [
{
type : "text" ,
text : projectsText ,
} ,
] ,
} ;
}
) ;
server . tool (
2025-04-03 11:51:17 +03:00
"get-package-documentation" ,
"Retrieves documentation for a specific package from Context7. Use 'list-available-packages' first to see what's available." ,
2025-03-31 15:19:29 +03:00
{
2025-04-03 11:51:17 +03:00
packageName : z
. string ( )
. describe (
"Name of the package/library to retrieve documentation for (e.g., 'upstash-redis', 'nextjs'). Must match exactly a package name from 'list-available-packages'."
) ,
topic : z
. string ( )
. describe (
"Specific topic within the package to focus the documentation on (e.g., 'hooks', 'routing')."
) ,
tokens : z
. number ( )
. min ( 5000 )
. optional ( )
. describe (
"Maximum number of tokens of documentation to retrieve (default: 5000).Higher values provide more comprehensive documentation but use more context window."
) ,
2025-03-31 15:19:29 +03:00
} ,
async ( { packageName , tokens = 5000 , topic = "" } ) = > {
2025-04-03 11:51:17 +03:00
const documentationText = await fetchPackageDocumentation ( packageName , tokens , 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-03 11:51:17 +03:00
text : "Documentation not found or not finalized for this package. Verify you've provided a valid package name exactly as listed by the 'list-available-packages' tool." ,
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 ) ;
} ) ;