Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ Documentation is cloned into a temporary directory, and Markdown files are index

For Cursor users, you can install the MCP server with a single click using the deeplink below:

[![Install MCP Server](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/install-mcp?name=pipe-cd.docs-mcp-server&config=eyJ0eXBlIjoic3RkaW8iLCJjb21tYW5kIjoibnB4IEBwaXBlLWNkL2RvY3MtbWNwLXNlcnZlckBsYXRlc3QifQ%3D%3D)
[![Install MCP Server](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en-US/install-mcp?name=pipe-cd.docs-mcp-server&config=eyJ0eXBlIjoic3RkaW8iLCJjb21tYW5kIjoibnB4IEBwaXBlLWNkL2RvY3MtbWNwLXNlcnZlckBsYXRlc3QifQ%3D%3D)

This will automatically configure the MCP server in your Cursor settings. After clicking the link, Cursor will prompt you to install the server.

Expand Down
4 changes: 2 additions & 2 deletions src/loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export async function loadDocsFromGitHub(): Promise<DocFile[]> {
}

try {
console.info(`Start cloning repo ${REPO} to ${targetDir}`);
console.error(`Start cloning repo ${REPO} to ${targetDir}`);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why should we use error over info here?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In a normal Node app console.info is fine. But MCP servers communicate over stdio, the client reads stdout expecting only valid JSON. Any non-JSON text (like "Successfully cloned...") breaks the protocol.console.error here doesn't mean something went wrong, it just routes the message to stderr, which MCP clients ignore (or display in debug logs)

await git.clone(REPO, targetDir, [
"--depth",
"1",
Expand All @@ -36,7 +36,7 @@ export async function loadDocsFromGitHub(): Promise<DocFile[]> {
]);
await git.cwd(targetDir);
await git.raw(["sparse-checkout", "set", DOCS_PATH]);
console.info(`Successfully cloned repo ${REPO} to ${targetDir}`);
console.error(`Successfully cloned repo ${REPO} to ${targetDir}`);
} catch (error) {
console.error(`Error while cloning repo ${REPO} to ${targetDir}: ${error}`);
throw error;
Expand Down
20 changes: 14 additions & 6 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ async function main() {

server.tool(
"search_docs",
"Full-text search over PipeCD docs. Query is space-separated keywords (AND search).",
{
query: z.string(),
offset: z.number(),
Expand Down Expand Up @@ -45,12 +46,19 @@ async function main() {
},
);
// NOTE: read_docs might not be called because search_docs contains contents.
server.tool("read_docs", { path: z.string() }, async ({ path }) => {
const doc = docsIndexes.find((doc) => doc.path === path);
return {
content: [{ type: "text", text: doc?.content ?? "document not found" }],
};
});
server.tool(
"read_docs",
'Returns the full content of a specified PipeCD doc page. Provide the relative path of the document (after "docs/content/en/").',
{ path: z.string() },
async ({ path }) => {
const doc = docsIndexes.find((doc) => doc.path === path);
return {
content: [
{ type: "text", text: doc?.content ?? "document not found" },
],
};
},
);

// Start receiving messages on stdin and sending messages on stdout
const transport = new StdioServerTransport();
Expand Down
Loading