@@ -5,10 +5,29 @@ import {
5
5
ResourceTemplate ,
6
6
} from '@modelcontextprotocol/sdk/server/mcp.js' ;
7
7
import Logger from './logger.js' ;
8
+ import { fileURLToPath } from 'url' ;
9
+
10
+ // Get the directory of the current module
11
+ const __filename = fileURLToPath ( import . meta. url ) ;
12
+ const __dirname = path . dirname ( __filename ) ;
8
13
9
14
// Configuration
10
15
export const RESOURCES_DIR = path . join ( process . cwd ( ) , 'resources' ) ;
11
16
17
+ // Try to use the package directory for resources if it exists
18
+ export async function getResourcesDir ( ) : Promise < string > {
19
+ const packageResourcesDir = path . join ( __dirname , '../../resources' ) ;
20
+ try {
21
+ await fs . access ( packageResourcesDir ) ;
22
+ return packageResourcesDir ;
23
+ } catch (
24
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
25
+ _error
26
+ ) {
27
+ return RESOURCES_DIR ;
28
+ }
29
+ }
30
+
12
31
/**
13
32
* Load a file's content from disk
14
33
*/
@@ -20,9 +39,9 @@ export async function loadFile(filePath: string): Promise<string> {
20
39
span . end ( 'success' ) ;
21
40
return content ;
22
41
} catch ( error ) {
23
- Logger . error ( `Failed to load file: ${ filePath } ` , error ) ;
42
+ Logger . error ( `Failed to load file` , error , { path : filePath } ) ;
24
43
span . end ( 'error' ) ;
25
- throw new Error ( `Failed to load file: ${ filePath } ` ) ;
44
+ throw error ;
26
45
}
27
46
}
28
47
@@ -36,34 +55,39 @@ export async function loadResources(
36
55
const resourceMap = new Map < string , string > ( ) ;
37
56
38
57
try {
39
- await fs . mkdir ( RESOURCES_DIR , { recursive : true } ) ;
40
- Logger . debug ( `Ensuring resources directory exists` , {
41
- path : RESOURCES_DIR ,
42
- } ) ;
58
+ // Get the resources directory
59
+ const resourcesDir = await getResourcesDir ( ) ;
60
+ await fs . mkdir ( resourcesDir , { recursive : true } ) ;
61
+ Logger . debug ( `Ensuring resources directory exists` , { path : resourcesDir } ) ;
43
62
44
- const files = await fs . readdir ( RESOURCES_DIR , { recursive : true } ) ;
63
+ const files = await fs . readdir ( resourcesDir ) ;
45
64
Logger . info ( `Found ${ files . length } potential resource files` , {
46
- directory : RESOURCES_DIR ,
65
+ directory : resourcesDir ,
47
66
} ) ;
48
67
49
68
let loadedCount = 0 ;
50
69
51
70
for ( const file of files ) {
52
- const fileSpan = Logger . span ( 'processResourceFile' , { file } ) ;
71
+ const resourceSpan = Logger . span ( 'processResourceFile' , { file } ) ;
72
+
73
+ if ( ! file . endsWith ( '.txt' ) ) {
74
+ Logger . trace ( `Skipping non-txt file` , { file } ) ;
75
+ resourceSpan . end ( 'skipped_non_txt' ) ;
76
+ continue ;
77
+ }
53
78
54
- // Skip directories and non-text files
55
- const filePath = path . join ( RESOURCES_DIR , file ) ;
79
+ const filePath = path . join ( resourcesDir , file ) ;
56
80
const stats = await fs . stat ( filePath ) ;
57
81
58
82
if ( stats . isDirectory ( ) ) {
59
83
Logger . trace ( `Skipping directory` , { path : filePath } ) ;
60
- fileSpan . end ( 'skipped_directory' ) ;
84
+ resourceSpan . end ( 'skipped_directory' ) ;
61
85
continue ;
62
86
}
63
87
64
88
// Convert file path to resource URI
65
89
// e.g., resources/docs/intro.txt -> docs/intro
66
- const relPath = path . relative ( RESOURCES_DIR , filePath ) ;
90
+ const relPath = path . relative ( resourcesDir , filePath ) ;
67
91
const resourcePath = relPath . replace ( / \. [ ^ / . ] + $ / , '' ) ; // Remove extension
68
92
const resourceUri = `file://${ resourcePath } ` ;
69
93
@@ -91,12 +115,12 @@ export async function loadResources(
91
115
uri : resourceUri ,
92
116
size : content . length ,
93
117
} ) ;
94
- fileSpan . end ( 'success' ) ;
118
+ resourceSpan . end ( 'success' ) ;
95
119
} catch ( error ) {
96
120
Logger . error ( `Failed to process resource file` , error , {
97
121
path : filePath ,
98
122
} ) ;
99
- fileSpan . end ( 'error' ) ;
123
+ resourceSpan . end ( 'error' ) ;
100
124
}
101
125
}
102
126
@@ -110,7 +134,7 @@ export async function loadResources(
110
134
const span = Logger . span ( 'dynamicResourceLoad' , { path : params . path } ) ;
111
135
try {
112
136
const resourcePath = params . path ;
113
- const filePath = path . join ( RESOURCES_DIR , resourcePath + '.txt' ) ;
137
+ const filePath = path . join ( resourcesDir , resourcePath + '.txt' ) ;
114
138
const content = await loadFile ( filePath ) ;
115
139
span . end ( 'success' ) ;
116
140
return {
0 commit comments