diff --git a/apps/website/content/docs/core-concepts/prompts.mdx b/apps/website/content/docs/core-concepts/prompts.mdx
index 6c24b5453..a20baba72 100644
--- a/apps/website/content/docs/core-concepts/prompts.mdx
+++ b/apps/website/content/docs/core-concepts/prompts.mdx
@@ -101,3 +101,34 @@ The default export function that performs the actual work.
- **Parameters**: Automatically typed from your schema using the built-in `InferSchema`.
- **Returns**: MCP-compatible response with content type.
- **Async**: Supports async operations for API calls, file I/O, etc.
+
+## Troubleshooting
+
+### Prompt Loading Errors
+
+When `xmcp` starts, it loads every file under your prompts directory.
+
+- Empty prompt files are skipped with a friendly warning
+- Files without a `default` export are skipped with a friendly warning
+- Real syntax or import errors still fail normally so you can see the full stack trace
+
+For example, if `src/prompts/draft.ts` is empty, startup will log:
+
+```txt
+[xmcp] Failed to load prompt file: src/prompts/draft.ts
+ -> File is empty.
+[xmcp] 1 prompt skipped due to empty files or missing default exports
+```
+
+If the file exists but does not export a default handler, startup will log:
+
+```txt
+[xmcp] Failed to load prompt file: src/prompts/draft.ts
+ -> File does not export a default prompt handler.
+```
+
+
+ Friendly handling is intentionally limited to empty files and missing default
+ exports. Invalid implementations and real import/syntax errors still surface
+ as normal runtime errors.
+
diff --git a/apps/website/content/docs/core-concepts/resources.mdx b/apps/website/content/docs/core-concepts/resources.mdx
index 9de55bac0..1abf0d491 100644
--- a/apps/website/content/docs/core-concepts/resources.mdx
+++ b/apps/website/content/docs/core-concepts/resources.mdx
@@ -101,3 +101,34 @@ The default export function that performs the actual work.
- **Parameters**: Automatically typed from your schema using the built-in `InferSchema`.
- **Returns**: MCP-compatible response with content type.
+
+## Troubleshooting
+
+### Resource Loading Errors
+
+When `xmcp` starts, it loads every file under your resources directory.
+
+- Empty resource files are skipped with a friendly warning
+- Files without a `default` export are skipped with a friendly warning
+- Real syntax or import errors still fail normally so you can see the full stack trace
+
+For example, if `src/resources/(drafts)/latest.ts` is empty, startup will log:
+
+```txt
+[xmcp] Failed to load resource file: src/resources/(drafts)/latest.ts
+ -> File is empty.
+[xmcp] 1 resource skipped due to empty files or missing default exports
+```
+
+If the file exists but does not export a default handler, startup will log:
+
+```txt
+[xmcp] Failed to load resource file: src/resources/(drafts)/latest.ts
+ -> File does not export a default resource handler.
+```
+
+
+ Friendly handling is intentionally limited to empty files and missing default
+ exports. Invalid implementations and real import/syntax errors still surface
+ as normal runtime errors.
+
diff --git a/packages/xmcp/src/compiler/index.ts b/packages/xmcp/src/compiler/index.ts
index 750991bfa..4d1f7abce 100644
--- a/packages/xmcp/src/compiler/index.ts
+++ b/packages/xmcp/src/compiler/index.ts
@@ -130,13 +130,18 @@ export async function compile({ onBuild }: CompileOptions = {}) {
onAdd: async (filePath) => {
addWatchedPath(promptPaths, filePath);
if (compilerStarted) {
- await generateCode();
+ await generateCode({ rebuildClientBundles: false });
+ }
+ },
+ onChange: async () => {
+ if (compilerStarted) {
+ await generateCode({ rebuildClientBundles: false });
}
},
onUnlink: async (filePath) => {
removeWatchedPath(promptPaths, filePath);
if (compilerStarted) {
- await generateCode();
+ await generateCode({ rebuildClientBundles: false });
}
},
});
@@ -154,13 +159,18 @@ export async function compile({ onBuild }: CompileOptions = {}) {
onAdd: async (filePath) => {
addWatchedPath(resourcePaths, filePath);
if (compilerStarted) {
- await generateCode();
+ await generateCode({ rebuildClientBundles: false });
+ }
+ },
+ onChange: async () => {
+ if (compilerStarted) {
+ await generateCode({ rebuildClientBundles: false });
}
},
onUnlink: async (filePath) => {
removeWatchedPath(resourcePaths, filePath);
if (compilerStarted) {
- await generateCode();
+ await generateCode({ rebuildClientBundles: false });
}
},
});
@@ -430,9 +440,16 @@ async function buildClientBundles(): Promise