Skip to content

Commit a72f35b

Browse files
committed
fix: guard startup logs for wide MCP STDIO compatibility
1 parent b371b9b commit a72f35b

File tree

5 files changed

+45
-25
lines changed

5 files changed

+45
-25
lines changed

CHANGELOG.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,16 @@
11
# Changelog
22

3+
## 1.2.1 (2025-12-31)
4+
5+
### Fixed
6+
7+
- **MCP Protocol Compatibility**: Fixed stderr output during MCP STDIO handshake for strict clients
8+
- All startup `console.error` calls now guarded with `CODEBASE_CONTEXT_DEBUG` env var
9+
- Zero stderr output during JSON-RPC handshake (required by Warp, OpenCode, MCPJam)
10+
- Debug logs available via `CODEBASE_CONTEXT_DEBUG=1` environment variable
11+
- Minimal implementation: 2 files changed, 46 insertions, 25 deletions
12+
- Reported by [@aolin480](https://github.com/aolin480) in [#2](https://github.com/PatrickSys/codebase-context/issues/2)
13+
314
## 1.2.0 (2025-12-29)
415

516
### Features

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ Now the agent checks patterns automatically instead of waiting for you to ask.
6767
|----------|---------|-------------|
6868
| `EMBEDDING_PROVIDER` | `transformers` | `openai` (fast, cloud) or `transformers` (local, private) |
6969
| `OPENAI_API_KEY` | - | Required if provider is `openai` |
70+
| `CODEBASE_CONTEXT_DEBUG` | - | Set to `1` to enable verbose logging (startup messages, analyzer registration) |
7071

7172
## Performance Note
7273

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "codebase-context",
3-
"version": "1.2.0",
3+
"version": "1.2.1",
44
"description": "MCP server for semantic codebase indexing and search - gives AI agents real understanding of your codebase",
55
"type": "module",
66
"main": "./dist/lib.js",

src/core/analyzer-registry.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,10 @@ export class AnalyzerRegistry {
1616
this.sortedAnalyzers = Array.from(this.analyzers.values())
1717
.sort((a, b) => b.priority - a.priority);
1818

19-
console.error(`Registered analyzer: ${analyzer.name} (priority: ${analyzer.priority})`);
19+
// Debug logging guarded by env var - avoids stderr output during MCP STDIO handshake
20+
if (process.env.CODEBASE_CONTEXT_DEBUG) {
21+
console.error(`[DEBUG] Registered analyzer: ${analyzer.name} (priority: ${analyzer.priority})`);
22+
}
2023
}
2124

2225
unregister(name: string): boolean {

src/index.ts

Lines changed: 28 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,13 @@ function resolveRootPath(): string {
3939
let rootPath = arg || envPath || process.cwd();
4040
rootPath = path.resolve(rootPath);
4141

42-
// Warn if using cwd as fallback
43-
if (!arg && !envPath) {
42+
// Warn if using cwd as fallback (guarded to avoid stderr during MCP STDIO handshake)
43+
if (!arg && !envPath && process.env.CODEBASE_CONTEXT_DEBUG) {
4444
console.error(
45-
`WARNING: No project path specified. Using current directory: ${rootPath}`
45+
`[DEBUG] No project path specified. Using current directory: ${rootPath}`
4646
);
4747
console.error(
48-
`Hint: Specify path as CLI argument or set CODEBASE_ROOT env var`
48+
`[DEBUG] Hint: Specify path as CLI argument or set CODEBASE_ROOT env var`
4949
);
5050
}
5151

@@ -991,14 +991,17 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
991991
});
992992

993993
async function main() {
994-
console.error("Codebase Context MCP Server");
995-
console.error(`Root: ${ROOT_PATH}`);
996-
console.error(
997-
`Analyzers: ${analyzerRegistry
998-
.getAll()
999-
.map((a) => a.name)
1000-
.join(", ")}`
1001-
);
994+
// Server startup banner (guarded to avoid stderr during MCP STDIO handshake)
995+
if (process.env.CODEBASE_CONTEXT_DEBUG) {
996+
console.error("[DEBUG] Codebase Context MCP Server");
997+
console.error(`[DEBUG] Root: ${ROOT_PATH}`);
998+
console.error(
999+
`[DEBUG] Analyzers: ${analyzerRegistry
1000+
.getAll()
1001+
.map((a) => a.name)
1002+
.join(", ")}`
1003+
);
1004+
}
10021005

10031006
// Validate root path exists and is a directory
10041007
try {
@@ -1014,31 +1017,33 @@ async function main() {
10141017
process.exit(1);
10151018
}
10161019

1017-
// Check for package.json to confirm it's a project root
1018-
try {
1019-
await fs.access(path.join(ROOT_PATH, "package.json"));
1020-
console.error(`Project detected: ${path.basename(ROOT_PATH)}`);
1021-
} catch {
1022-
console.error(
1023-
`WARNING: No package.json found. This may not be a project root.`
1024-
);
1020+
// Check for package.json to confirm it's a project root (guarded to avoid stderr during handshake)
1021+
if (process.env.CODEBASE_CONTEXT_DEBUG) {
1022+
try {
1023+
await fs.access(path.join(ROOT_PATH, "package.json"));
1024+
console.error(`[DEBUG] Project detected: ${path.basename(ROOT_PATH)}`);
1025+
} catch {
1026+
console.error(
1027+
`[DEBUG] WARNING: No package.json found. This may not be a project root.`
1028+
);
1029+
}
10251030
}
10261031

10271032
const needsIndex = await shouldReindex();
10281033

10291034
if (needsIndex) {
1030-
console.error("Starting indexing...");
1035+
if (process.env.CODEBASE_CONTEXT_DEBUG) console.error("[DEBUG] Starting indexing...");
10311036
performIndexing();
10321037
} else {
1033-
console.error("Index found. Ready.");
1038+
if (process.env.CODEBASE_CONTEXT_DEBUG) console.error("[DEBUG] Index found. Ready.");
10341039
indexState.status = "ready";
10351040
indexState.lastIndexed = new Date();
10361041
}
10371042

10381043
const transport = new StdioServerTransport();
10391044
await server.connect(transport);
10401045

1041-
console.error("Server ready");
1046+
if (process.env.CODEBASE_CONTEXT_DEBUG) console.error("[DEBUG] Server ready");
10421047
}
10431048

10441049
// Export server components for programmatic use

0 commit comments

Comments
 (0)