Skip to content

Commit a0addd6

Browse files
committed
🐛 FIX: formating
1 parent a074f63 commit a0addd6

File tree

4 files changed

+162
-176
lines changed

4 files changed

+162
-176
lines changed

packages/cli/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ Please follow the [Langbase documentation](https://langbase.com/docs) for the la
99
## Installation
1010

1111
```bash
12-
npm install -g @langbase/cli
12+
npx @langbase/cli
1313
```
1414

1515
# Usage
Lines changed: 43 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,56 @@
11
import { JSDOM } from 'jsdom';
2-
// Fetches a list of all the docs on the langbase website
2+
3+
/**
4+
* Fetches a list of all the docs on the langbase website
5+
* @returns {Promise<string>} A promise that resolves to a string of all the docs on the langbase website
6+
*/
7+
38
export async function fetchDocsList() {
4-
try {
5-
const response = await fetch('https://langbase.com/docs/llms.txt');
9+
try {
10+
const response = await fetch('https://langbase.com/docs/llms.txt');
611

7-
if (!response.ok) {
8-
throw new Error('Failed to fetch docs');
9-
}
12+
if (!response.ok) {
13+
throw new Error('Failed to fetch docs');
14+
}
1015

11-
const text = await response.text();
12-
return text;
16+
const text = await response.text();
17+
return text;
1318

14-
} catch (error) {
15-
throw new Error('Failed to fetch docs ' + JSON.stringify(error));
16-
}
19+
} catch (error) {
20+
throw new Error('Failed to fetch docs ' + JSON.stringify(error));
21+
}
1722
}
1823

24+
/**
25+
* Fetches and converts a blog post to markdown
26+
* @param {string} url - The URL of the blog post to fetch
27+
* @returns {Promise<string>} A promise that resolves to a string of the blog post in markdown format
28+
*/
1929

20-
// Helper function to fetch and convert a blog post to markdown
2130
export async function fetchDocsPost(url: string): Promise<string> {
22-
try {
23-
const response = await fetch(url);
24-
if (!response.ok) {
25-
throw new Error('Failed to fetch blog post');
26-
}
31+
try {
32+
const response = await fetch(url);
33+
if (!response.ok) {
34+
throw new Error('Failed to fetch blog post');
35+
}
2736

28-
const html = await response.text();
37+
const html = await response.text();
2938

30-
const dom = new JSDOM(html);
31-
const document = dom.window.document;
32-
// Remove Next.js initialization code
33-
const scripts = document.querySelectorAll('script');
34-
scripts.forEach(script => script.remove());
35-
36-
// Get the main content
37-
const content = document.body.textContent?.trim() || '';
38-
if (!content) {
39-
throw new Error('No content found in docs');
40-
}
41-
42-
return content;
39+
const dom = new JSDOM(html);
40+
const document = dom.window.document;
41+
// Remove Next.js initialization code
42+
const scripts = document.querySelectorAll('script');
43+
scripts.forEach(script => script.remove());
44+
45+
// Get the main content
46+
const content = document.body.textContent?.trim() || '';
47+
if (!content) {
48+
throw new Error('No content found in docs');
49+
}
50+
51+
return content;
52+
4353
} catch (error) {
44-
throw new Error(`Failed to fetch docs: ${error instanceof Error ? error.message : 'Unknown error'}`);
54+
throw new Error(`Failed to fetch docs: ${error instanceof Error ? error.message : 'Unknown error'}`);
4555
}
46-
}
56+
}

packages/cli/src/docs-mcp-server/index.ts

Lines changed: 114 additions & 141 deletions
Original file line numberDiff line numberDiff line change
@@ -5,173 +5,146 @@ import { fetchDocsList, fetchDocsPost } from "./docs"
55

66

77
export async function docsMcpServer() {
8-
// Create server instance with resource support
98
const server = new McpServer({
10-
name: "langbase-docs-server",
11-
version: "1.0.0"
9+
name: "langbase-docs-server",
10+
version: "1.0.0"
1211
});
1312

14-
15-
// SDK-specific tool
1613
server.tool(
17-
"docs-route-finder",
18-
"Searches through all available documentation routes and returns relevant paths based on the user's query. This tool helps navigate the documentation by finding the most appropriate sections that match the search criteria.",
19-
{
20-
query: z.string().describe(`A refined search term extracted from the user's question.
21-
For example, if user asks 'How do I create a pipe?', the query would be 'SDK Pipe'.
22-
This should be the specific concept or topic to search for in the documentation.
23-
Treat keyword add as create if user ask for Eg. 'How do I add memory to pipe?' the query should be 'create memory'`),
24-
},
25-
async ({ query }) => {
26-
const docs = await fetchDocsList()
27-
// search through the docs and return the most relevent path based on the query
28-
// Split docs into lines and create an array of documentation entries
29-
const docLines = docs.split('\n').filter(line => line.trim());
14+
"docs-route-finder",
15+
"Searches through all available documentation routes and returns relevant paths based on the user's query. This tool helps navigate the documentation by finding the most appropriate sections that match the search criteria.",
16+
{ query: z.string().describe(`A refined search term extracted from the user's question.
17+
For example, if user asks 'How do I create a pipe?', the query would be 'SDK Pipe'.
18+
This should be the specific concept or topic to search for in the documentation.
19+
Treat keyword add as create if user ask for Eg. 'How do I add memory to pipe?' the query should be 'create memory'`)
20+
},
21+
async ({ query }) => {
22+
const docs = await fetchDocsList()
23+
// search through the docs and return the most relevent path based on the query
24+
const docLines = docs.split('\n').filter(line => line.trim());
3025

31-
// Create a simple scoring system for relevance
32-
const getRelevanceScore = (line: string, searchQuery: string) => {
33-
const lowerLine = line.toLowerCase();
34-
const lowerQuery = searchQuery.toLowerCase();
35-
// Higher score for exact matches
36-
if (lowerLine.includes(lowerQuery)) {
37-
return 3;
38-
}
3926

40-
// Score based on word matches
41-
const queryWords = lowerQuery.split(' ');
42-
return queryWords.reduce((score, word) => {
43-
return score + (lowerLine.includes(word) ? 1 : 0);
44-
}, 0);
45-
};
46-
47-
// Score and sort the documentation entries
48-
const scoredDocs = docLines
49-
.map(line => ({
50-
line,
51-
score: getRelevanceScore(line, query)
52-
}))
53-
.sort((a, b) => b.score - a.score)
54-
.filter(doc => doc.score > 0)
55-
.slice(0, 3); // Get top 3 most relevant results
56-
27+
const getRelevanceScore = (line: string, searchQuery: string) => {
28+
const lowerLine = line.toLowerCase();
29+
const lowerQuery = searchQuery.toLowerCase();
30+
// Higher score for exact matches
31+
if (lowerLine.includes(lowerQuery)) {
32+
return 3;
33+
}
34+
35+
// Score based on word matches
36+
const queryWords = lowerQuery.split(' ');
37+
return queryWords.reduce((score, word) => {
38+
return score + (lowerLine.includes(word) ? 1 : 0);
39+
}, 0);
40+
};
41+
42+
// Score and sort the documentation entries
43+
const scoredDocs = docLines
44+
.map(line => ({
45+
line,
46+
score: getRelevanceScore(line, query)
47+
}))
48+
.sort((a, b) => b.score - a.score)
49+
.filter(doc => doc.score > 0)
50+
.slice(0, 3); // Get top 3 most relevant results
51+
5752

58-
if (scoredDocs.length === 0) {
59-
return {
60-
content: [{
61-
type: "text",
62-
text: "No relevant documentation found for the query: " + query
63-
}]
64-
};
53+
if (scoredDocs.length === 0) {
54+
return {
55+
content: [{
56+
type: "text",
57+
text: "No relevant documentation found for the query: " + query
58+
}]
59+
};
60+
}
61+
62+
const results = scoredDocs.map(doc => doc.line).join('\n');
63+
64+
return {
65+
content: [{
66+
type: "text",
67+
text: results
68+
}]
69+
};
6570
}
66-
67-
// Extract URLs and create formatted response
68-
const results = scoredDocs.map(doc => doc.line).join('\n');
69-
70-
return {
71-
content: [
72-
{
73-
type: "text",
74-
text: results,
75-
},
76-
],
77-
};
78-
}
7971
);
8072

81-
8273
server.tool(
83-
"sdk-documentation-fetcher",
84-
"Fetches detailed SDK documentation, specializing in implementation guides for core features like pipes, memory, and tools. This is the primary source for the latest SDK documentation and should be consulted first for questions about creating or implementing SDK components. Use this tool for detailed step-by-step instructions on building pipes, configuring memory systems, and developing custom tools.",
85-
{
86-
url: z.string().describe("URL of a specific SDK page to fetch. Format: /sdk/..."),
87-
},
88-
async ({ url }) => {
89-
const content = await fetchDocsPost(`https://langbase.com/docs${url}`);
90-
return {
91-
content: [
92-
{
93-
type: "text",
94-
text: content,
95-
},
96-
],
97-
};
98-
}
74+
"sdk-documentation-fetcher",
75+
"Fetches detailed SDK documentation, specializing in implementation guides for core features like pipes, memory, and tools. This is the primary source for the latest SDK documentation and should be consulted first for questions about creating or implementing SDK components. Use this tool for detailed step-by-step instructions on building pipes, configuring memory systems, and developing custom tools.",
76+
{ url: z.string().describe("URL of a specific SDK page to fetch. Format: /sdk/...") },
77+
async ({ url }) => {
78+
const content = await fetchDocsPost(`https://langbase.com/docs${url}`);
79+
return {
80+
content: [{
81+
type: "text",
82+
text: content
83+
}]
84+
};
85+
}
9986
);
10087

10188
server.tool(
102-
"examples-tool",
103-
"Fetches code examples and sample implementations from the documentation. Use this tool when users specifically request examples, sample code, or implementation demonstrations. This tool provides practical code snippets and complete working examples that demonstrate how to implement various features.",
104-
{
105-
url: z.string().describe("URL of a specific examples page to fetch. Format: /examples/..."),
106-
},
107-
async ({ url }) => {
108-
const content = await fetchDocsPost(`https://langbase.com/docs${url}`);
109-
return {
110-
content: [
111-
{
112-
type: "text",
113-
text: content,
114-
},
115-
],
116-
};
117-
}
89+
"examples-tool",
90+
"Fetches code examples and sample implementations from the documentation. Use this tool when users specifically request examples, sample code, or implementation demonstrations. This tool provides practical code snippets and complete working examples that demonstrate how to implement various features.",
91+
{ url: z.string().describe("URL of a specific examples page to fetch. Format: /examples/...") },
92+
async ({ url }) => {
93+
const content = await fetchDocsPost(`https://langbase.com/docs${url}`);
94+
return {
95+
content: [{
96+
type: "text",
97+
text: content
98+
}]
99+
};
100+
}
118101
);
119102

120103
server.tool(
121-
"guide-tool",
122-
"Fetches detailed guides and tutorials from the documentation. Use this tool when users explicitly request guides, tutorials, or how-to content. This tool provides step-by-step instructions and practical examples for implementing various features.",
123-
{
124-
url: z.string().describe("URL of a specific guide page to fetch. Format: /guides/..."),
125-
},
126-
async ({ url }) => {
127-
const content = await fetchDocsPost(`https://langbase.com/docs${url}`);
128-
return {
129-
content: [
130-
{
131-
type: "text",
132-
text: content,
133-
},
134-
],
135-
};
136-
}
104+
"guide-tool",
105+
"Fetches detailed guides and tutorials from the documentation. Use this tool when users explicitly request guides, tutorials, or how-to content. This tool provides step-by-step instructions and practical examples for implementing various features.",
106+
{ url: z.string().describe("URL of a specific guide page to fetch. Format: /guides/...") },
107+
async ({ url }) => {
108+
const content = await fetchDocsPost(`https://langbase.com/docs${url}`);
109+
return {
110+
content: [{
111+
type: "text",
112+
text: content
113+
}]
114+
};
115+
}
137116
);
138117

139118
server.tool(
140-
"api-reference-tool",
141-
"Fetches API reference documentation. Use this tool ONLY when the user explicitly asks about API endpoints, REST API calls, or programmatically creating/updating/deleting resources (like pipes, memory, etc.) through the API interface. For general SDK implementation questions, use the sdk-documentation-fetcher instead.",
142-
{
143-
url: z.string().describe("URL of a specific api-reference page to fetch. Format: /api-reference/..."),
144-
},
145-
async ({ url }) => {
146-
const content = await fetchDocsPost(`https://langbase.com/docs${url}`);
147-
return {
148-
content: [
149-
{
150-
type: "text",
151-
text: content,
152-
},
153-
],
154-
};
155-
}
119+
"api-reference-tool",
120+
"Fetches API reference documentation. Use this tool ONLY when the user explicitly asks about API endpoints, REST API calls, or programmatically creating/updating/deleting resources (like pipes, memory, etc.) through the API interface. For general SDK implementation questions, use the sdk-documentation-fetcher instead.",
121+
{ url: z.string().describe("URL of a specific api-reference page to fetch. Format: /api-reference/...") },
122+
async ({ url }) => {
123+
const content = await fetchDocsPost(`https://langbase.com/docs${url}`);
124+
return {
125+
content: [{
126+
type: "text",
127+
text: content,
128+
}]
129+
};
130+
}
156131
);
157132

158-
159133
async function main() {
160-
const transport = new StdioServerTransport();
161-
162-
try {
163-
await server.connect(transport);
164-
console.error("Langbase service MCP Server running on stdio");
165-
} catch (error) {
166-
console.error("Error connecting to transport:", error);
167-
process.exit(1);
168-
}
134+
const transport = new StdioServerTransport();
135+
136+
try {
137+
await server.connect(transport);
138+
console.error("Langbase service MCP Server running on stdio");
139+
} catch (error) {
140+
console.error("Error connecting to transport:", error);
141+
process.exit(1);
142+
}
169143
}
170144

171145
main().catch((error) => {
172-
console.error("Fatal error in main():", error);
173-
process.exit(1);
146+
console.error("Fatal error in main():", error);
147+
process.exit(1);
174148
});
175-
176149
}
177150

0 commit comments

Comments
 (0)