@novorb/mcp-core 2.1.2 → 3.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (240) hide show
  1. package/README.md +77 -163
  2. package/bin/mcp-core-jest.mjs +112 -0
  3. package/dist/auth.d.ts +57 -0
  4. package/dist/auth.d.ts.map +1 -0
  5. package/dist/auth.js +74 -0
  6. package/dist/auth.js.map +1 -0
  7. package/dist/bootstrap.d.ts +129 -0
  8. package/dist/bootstrap.d.ts.map +1 -0
  9. package/dist/bootstrap.js +206 -0
  10. package/dist/bootstrap.js.map +1 -0
  11. package/dist/client-input.d.ts +72 -0
  12. package/dist/client-input.d.ts.map +1 -0
  13. package/dist/client-input.js +109 -0
  14. package/dist/client-input.js.map +1 -0
  15. package/dist/credential-checks.d.ts +80 -0
  16. package/dist/credential-checks.d.ts.map +1 -0
  17. package/dist/credential-checks.js +189 -0
  18. package/dist/credential-checks.js.map +1 -0
  19. package/dist/credential-health.d.ts +12 -0
  20. package/dist/credential-health.d.ts.map +1 -0
  21. package/dist/credential-health.js +12 -0
  22. package/dist/credential-health.js.map +1 -0
  23. package/dist/credential-report.d.ts +46 -0
  24. package/dist/credential-report.d.ts.map +1 -0
  25. package/dist/credential-report.js +135 -0
  26. package/dist/credential-report.js.map +1 -0
  27. package/dist/credential-status-tool.d.ts +20 -0
  28. package/dist/credential-status-tool.d.ts.map +1 -0
  29. package/dist/credential-status-tool.js +33 -0
  30. package/dist/credential-status-tool.js.map +1 -0
  31. package/dist/credentials.d.ts +288 -0
  32. package/dist/credentials.d.ts.map +1 -0
  33. package/dist/credentials.js +652 -0
  34. package/dist/credentials.js.map +1 -0
  35. package/dist/express-peers.d.ts +29 -0
  36. package/dist/express-peers.d.ts.map +1 -0
  37. package/dist/express-peers.js +36 -0
  38. package/dist/express-peers.js.map +1 -0
  39. package/dist/express.d.ts +74 -0
  40. package/dist/express.d.ts.map +1 -0
  41. package/dist/express.js +164 -0
  42. package/dist/express.js.map +1 -0
  43. package/dist/http-client.d.ts +277 -42
  44. package/dist/http-client.d.ts.map +1 -1
  45. package/dist/http-client.js +620 -180
  46. package/dist/http-client.js.map +1 -1
  47. package/dist/index.d.ts +27 -6
  48. package/dist/index.d.ts.map +1 -1
  49. package/dist/index.js +47 -8
  50. package/dist/index.js.map +1 -1
  51. package/dist/limits.d.ts +28 -0
  52. package/dist/limits.d.ts.map +1 -0
  53. package/dist/limits.js +37 -0
  54. package/dist/limits.js.map +1 -0
  55. package/dist/list-pagination.d.ts +41 -0
  56. package/dist/list-pagination.d.ts.map +1 -0
  57. package/dist/list-pagination.js +104 -0
  58. package/dist/list-pagination.js.map +1 -0
  59. package/dist/net.d.ts +112 -0
  60. package/dist/net.d.ts.map +1 -0
  61. package/dist/net.js +490 -0
  62. package/dist/net.js.map +1 -0
  63. package/dist/notifications.d.ts +78 -0
  64. package/dist/notifications.d.ts.map +1 -0
  65. package/dist/notifications.js +173 -0
  66. package/dist/notifications.js.map +1 -0
  67. package/dist/pagination.d.ts +236 -5
  68. package/dist/pagination.d.ts.map +1 -1
  69. package/dist/pagination.js +393 -6
  70. package/dist/pagination.js.map +1 -1
  71. package/dist/prompts.d.ts +70 -0
  72. package/dist/prompts.d.ts.map +1 -0
  73. package/dist/prompts.js +109 -0
  74. package/dist/prompts.js.map +1 -0
  75. package/dist/protocol-errors.d.ts +15 -0
  76. package/dist/protocol-errors.d.ts.map +1 -0
  77. package/dist/protocol-errors.js +28 -0
  78. package/dist/protocol-errors.js.map +1 -0
  79. package/dist/protocol-logging.d.ts +37 -0
  80. package/dist/protocol-logging.d.ts.map +1 -0
  81. package/dist/protocol-logging.js +77 -0
  82. package/dist/protocol-logging.js.map +1 -0
  83. package/dist/rate-limiter.d.ts +36 -0
  84. package/dist/rate-limiter.d.ts.map +1 -0
  85. package/dist/rate-limiter.js +79 -0
  86. package/dist/rate-limiter.js.map +1 -0
  87. package/dist/request-state.d.ts +74 -0
  88. package/dist/request-state.d.ts.map +1 -0
  89. package/dist/request-state.js +190 -0
  90. package/dist/request-state.js.map +1 -0
  91. package/dist/resources.d.ts +181 -0
  92. package/dist/resources.d.ts.map +1 -0
  93. package/dist/resources.js +302 -0
  94. package/dist/resources.js.map +1 -0
  95. package/dist/result-limits.d.ts +80 -0
  96. package/dist/result-limits.d.ts.map +1 -0
  97. package/dist/result-limits.js +248 -0
  98. package/dist/result-limits.js.map +1 -0
  99. package/dist/retry.d.ts +79 -23
  100. package/dist/retry.d.ts.map +1 -1
  101. package/dist/retry.js +170 -57
  102. package/dist/retry.js.map +1 -1
  103. package/dist/sdk/client-stdio.d.ts +6 -0
  104. package/dist/sdk/client-stdio.d.ts.map +1 -0
  105. package/dist/sdk/client-stdio.js +6 -0
  106. package/dist/sdk/client-stdio.js.map +1 -0
  107. package/dist/sdk/client.d.ts +6 -0
  108. package/dist/sdk/client.d.ts.map +1 -0
  109. package/dist/sdk/client.js +6 -0
  110. package/dist/sdk/client.js.map +1 -0
  111. package/dist/sdk/express.d.ts +3 -0
  112. package/dist/sdk/express.d.ts.map +1 -0
  113. package/dist/sdk/express.js +11 -0
  114. package/dist/sdk/express.js.map +1 -0
  115. package/dist/sdk/node.d.ts +6 -0
  116. package/dist/sdk/node.d.ts.map +1 -0
  117. package/dist/sdk/node.js +6 -0
  118. package/dist/sdk/node.js.map +1 -0
  119. package/dist/sdk/server-stdio.d.ts +6 -0
  120. package/dist/sdk/server-stdio.d.ts.map +1 -0
  121. package/dist/sdk/server-stdio.js +6 -0
  122. package/dist/sdk/server-stdio.js.map +1 -0
  123. package/dist/sdk/server.d.ts +6 -0
  124. package/dist/sdk/server.d.ts.map +1 -0
  125. package/dist/sdk/server.js +6 -0
  126. package/dist/sdk/server.js.map +1 -0
  127. package/dist/server.d.ts +88 -35
  128. package/dist/server.d.ts.map +1 -1
  129. package/dist/server.js +98 -44
  130. package/dist/server.js.map +1 -1
  131. package/dist/task-request.d.ts +20 -0
  132. package/dist/task-request.d.ts.map +1 -0
  133. package/dist/task-request.js +43 -0
  134. package/dist/task-request.js.map +1 -0
  135. package/dist/task-store.d.ts +230 -0
  136. package/dist/task-store.d.ts.map +1 -0
  137. package/dist/task-store.js +459 -0
  138. package/dist/task-store.js.map +1 -0
  139. package/dist/task-tools.d.ts +115 -0
  140. package/dist/task-tools.d.ts.map +1 -0
  141. package/dist/task-tools.js +397 -0
  142. package/dist/task-tools.js.map +1 -0
  143. package/dist/testing/client.d.ts +25 -0
  144. package/dist/testing/client.d.ts.map +1 -0
  145. package/dist/testing/client.js +11 -0
  146. package/dist/testing/client.js.map +1 -0
  147. package/dist/testing/in-memory.d.ts +26 -0
  148. package/dist/testing/in-memory.d.ts.map +1 -0
  149. package/dist/testing/in-memory.js +41 -0
  150. package/dist/testing/in-memory.js.map +1 -0
  151. package/dist/testing/index.d.ts +20 -0
  152. package/dist/testing/index.d.ts.map +1 -0
  153. package/dist/testing/index.js +20 -0
  154. package/dist/testing/index.js.map +1 -0
  155. package/dist/testing/isolated-dirs.d.ts +27 -0
  156. package/dist/testing/isolated-dirs.d.ts.map +1 -0
  157. package/dist/testing/isolated-dirs.js +67 -0
  158. package/dist/testing/isolated-dirs.js.map +1 -0
  159. package/dist/testing/logs.d.ts +61 -0
  160. package/dist/testing/logs.d.ts.map +1 -0
  161. package/dist/testing/logs.js +113 -0
  162. package/dist/testing/logs.js.map +1 -0
  163. package/dist/testing/raw-http.d.ts +25 -0
  164. package/dist/testing/raw-http.d.ts.map +1 -0
  165. package/dist/testing/raw-http.js +41 -0
  166. package/dist/testing/raw-http.js.map +1 -0
  167. package/dist/testing/raw-peer.d.ts +43 -0
  168. package/dist/testing/raw-peer.d.ts.map +1 -0
  169. package/dist/testing/raw-peer.js +101 -0
  170. package/dist/testing/raw-peer.js.map +1 -0
  171. package/dist/testing/recording-server.d.ts +38 -0
  172. package/dist/testing/recording-server.d.ts.map +1 -0
  173. package/dist/testing/recording-server.js +38 -0
  174. package/dist/testing/recording-server.js.map +1 -0
  175. package/dist/testing/server-process.d.ts +76 -0
  176. package/dist/testing/server-process.d.ts.map +1 -0
  177. package/dist/testing/server-process.js +241 -0
  178. package/dist/testing/server-process.js.map +1 -0
  179. package/dist/testing/tools.d.ts +53 -0
  180. package/dist/testing/tools.d.ts.map +1 -0
  181. package/dist/testing/tools.js +98 -0
  182. package/dist/testing/tools.js.map +1 -0
  183. package/dist/testing/unit.d.ts +52 -0
  184. package/dist/testing/unit.d.ts.map +1 -0
  185. package/dist/testing/unit.js +95 -0
  186. package/dist/testing/unit.js.map +1 -0
  187. package/dist/tools.d.ts +205 -0
  188. package/dist/tools.d.ts.map +1 -0
  189. package/dist/tools.js +370 -0
  190. package/dist/tools.js.map +1 -0
  191. package/dist/transport.d.ts +143 -52
  192. package/dist/transport.d.ts.map +1 -1
  193. package/dist/transport.js +292 -123
  194. package/dist/transport.js.map +1 -1
  195. package/dist/url-path.d.ts +49 -0
  196. package/dist/url-path.d.ts.map +1 -0
  197. package/dist/url-path.js +165 -0
  198. package/dist/url-path.js.map +1 -0
  199. package/dist/utils/dataStore.d.ts +143 -0
  200. package/dist/utils/dataStore.d.ts.map +1 -0
  201. package/dist/utils/dataStore.js +429 -0
  202. package/dist/utils/dataStore.js.map +1 -0
  203. package/dist/utils/envLoader.d.ts +129 -0
  204. package/dist/utils/envLoader.d.ts.map +1 -0
  205. package/dist/utils/envLoader.js +399 -0
  206. package/dist/utils/envLoader.js.map +1 -0
  207. package/dist/utils/logger.d.ts +181 -0
  208. package/dist/utils/logger.d.ts.map +1 -0
  209. package/dist/utils/logger.js +664 -0
  210. package/dist/utils/logger.js.map +1 -0
  211. package/dist/utils/redact.d.ts +50 -0
  212. package/dist/utils/redact.d.ts.map +1 -0
  213. package/dist/utils/redact.js +318 -0
  214. package/dist/utils/redact.js.map +1 -0
  215. package/docs/api-reference.md +29 -0
  216. package/docs/building-a-server.md +63 -0
  217. package/docs/credentials.md +131 -0
  218. package/docs/data-store.md +37 -0
  219. package/docs/env.md +38 -0
  220. package/docs/features.md +28 -0
  221. package/docs/http-client.md +116 -0
  222. package/docs/logger.md +100 -0
  223. package/docs/migrating-to-v3.md +45 -0
  224. package/docs/outbound-urls.md +104 -0
  225. package/docs/pagination.md +45 -0
  226. package/docs/protocol-features.md +62 -0
  227. package/docs/resources-prompts-tasks.md +95 -0
  228. package/docs/sdk.md +33 -0
  229. package/docs/server.md +68 -0
  230. package/docs/testing-harness.md +139 -0
  231. package/docs/testing.md +151 -0
  232. package/docs/tools.md +88 -0
  233. package/docs/transport.md +85 -0
  234. package/examples/testing/tools.integration.test.example.ts +312 -0
  235. package/examples/testing/tools.unit.test.example.ts +149 -0
  236. package/package.json +130 -17
  237. package/dist/logger.d.ts +0 -80
  238. package/dist/logger.d.ts.map +0 -1
  239. package/dist/logger.js +0 -237
  240. package/dist/logger.js.map +0 -1
package/package.json CHANGED
@@ -1,23 +1,48 @@
1
1
  {
2
2
  "name": "@novorb/mcp-core",
3
- "version": "2.1.2",
4
- "description": "Shared utilities for MCP servers — logger, HTTP client, retry, pagination, transport",
3
+ "version": "3.0.1",
4
+ "description": "Shared utilities for MCP servers: the SDK v2 surface, logger, HTTP client, retry, pagination, transport",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",
8
+ "bin": {
9
+ "mcp-core-jest": "bin/mcp-core-jest.mjs"
10
+ },
8
11
  "exports": {
9
12
  ".": "./dist/index.js",
10
- "./logger": "./dist/logger.js",
13
+ "./logger": "./dist/utils/logger.js",
11
14
  "./retry": "./dist/retry.js",
12
15
  "./pagination": "./dist/pagination.js",
13
16
  "./http-client": "./dist/http-client.js",
14
17
  "./transport": "./dist/transport.js",
15
- "./server": "./dist/server.js"
18
+ "./server": "./dist/server.js",
19
+ "./tools": "./dist/tools.js",
20
+ "./credentials": "./dist/credential-health.js",
21
+ "./bootstrap": "./dist/bootstrap.js",
22
+ "./env": "./dist/utils/envLoader.js",
23
+ "./data-store": "./dist/utils/dataStore.js",
24
+ "./net": "./dist/net.js",
25
+ "./url-path": "./dist/url-path.js",
26
+ "./auth": "./dist/auth.js",
27
+ "./express": "./dist/express.js",
28
+ "./notifications": "./dist/notifications.js",
29
+ "./prompts": "./dist/prompts.js",
30
+ "./resources": "./dist/resources.js",
31
+ "./request-state": "./dist/request-state.js",
32
+ "./task-store": "./dist/task-store.js",
33
+ "./task-tools": "./dist/task-tools.js",
34
+ "./testing": "./dist/testing/index.js",
35
+ "./sdk/server": "./dist/sdk/server.js",
36
+ "./sdk/server/stdio": "./dist/sdk/server-stdio.js",
37
+ "./sdk/node": "./dist/sdk/node.js",
38
+ "./sdk/client": "./dist/sdk/client.js",
39
+ "./sdk/client/stdio": "./dist/sdk/client-stdio.js",
40
+ "./sdk/express": "./dist/sdk/express.js"
16
41
  },
17
42
  "typesVersions": {
18
43
  "*": {
19
44
  "logger": [
20
- "dist/logger.d.ts"
45
+ "dist/utils/logger.d.ts"
21
46
  ],
22
47
  "retry": [
23
48
  "dist/retry.d.ts"
@@ -33,6 +58,72 @@
33
58
  ],
34
59
  "server": [
35
60
  "dist/server.d.ts"
61
+ ],
62
+ "tools": [
63
+ "dist/tools.d.ts"
64
+ ],
65
+ "credentials": [
66
+ "dist/credential-health.d.ts"
67
+ ],
68
+ "bootstrap": [
69
+ "dist/bootstrap.d.ts"
70
+ ],
71
+ "env": [
72
+ "dist/utils/envLoader.d.ts"
73
+ ],
74
+ "data-store": [
75
+ "dist/utils/dataStore.d.ts"
76
+ ],
77
+ "net": [
78
+ "dist/net.d.ts"
79
+ ],
80
+ "url-path": [
81
+ "dist/url-path.d.ts"
82
+ ],
83
+ "auth": [
84
+ "dist/auth.d.ts"
85
+ ],
86
+ "express": [
87
+ "dist/express.d.ts"
88
+ ],
89
+ "notifications": [
90
+ "dist/notifications.d.ts"
91
+ ],
92
+ "prompts": [
93
+ "dist/prompts.d.ts"
94
+ ],
95
+ "resources": [
96
+ "dist/resources.d.ts"
97
+ ],
98
+ "request-state": [
99
+ "dist/request-state.d.ts"
100
+ ],
101
+ "task-store": [
102
+ "dist/task-store.d.ts"
103
+ ],
104
+ "task-tools": [
105
+ "dist/task-tools.d.ts"
106
+ ],
107
+ "testing": [
108
+ "dist/testing/index.d.ts"
109
+ ],
110
+ "sdk/server": [
111
+ "dist/sdk/server.d.ts"
112
+ ],
113
+ "sdk/server/stdio": [
114
+ "dist/sdk/server-stdio.d.ts"
115
+ ],
116
+ "sdk/node": [
117
+ "dist/sdk/node.d.ts"
118
+ ],
119
+ "sdk/client": [
120
+ "dist/sdk/client.d.ts"
121
+ ],
122
+ "sdk/client/stdio": [
123
+ "dist/sdk/client-stdio.d.ts"
124
+ ],
125
+ "sdk/express": [
126
+ "dist/sdk/express.d.ts"
36
127
  ]
37
128
  }
38
129
  },
@@ -57,36 +148,58 @@
57
148
  "url": "https://github.com/Novorb/mcp-core/issues"
58
149
  },
59
150
  "author": "novorb",
151
+ "peerDependencies": {
152
+ "@modelcontextprotocol/express": "~2.0.2",
153
+ "express": "^4.18.0 || ^5.0.0"
154
+ },
155
+ "peerDependenciesMeta": {
156
+ "@modelcontextprotocol/express": {
157
+ "optional": true
158
+ },
159
+ "express": {
160
+ "optional": true
161
+ }
162
+ },
60
163
  "dependencies": {
61
- "@modelcontextprotocol/sdk": "^1.30.0",
62
- "axios": "^1.20.0",
63
- "axios-retry": "^4.5.0"
164
+ "@modelcontextprotocol/client": "~2.3.1",
165
+ "@modelcontextprotocol/node": "~2.1.1",
166
+ "@modelcontextprotocol/server": "~2.3.1",
167
+ "axios": "^1.20.0"
64
168
  },
65
169
  "devDependencies": {
66
170
  "@biomejs/biome": "^2.5.13",
67
171
  "@jest/globals": "^30.3.0",
172
+ "@modelcontextprotocol/express": "~2.0.2",
173
+ "@modelcontextprotocol/ext-tasks": "0.2.2",
68
174
  "@secretlint/secretlint-rule-preset-recommend": "^13.0.5",
175
+ "@types/express": "^5.0.6",
69
176
  "@types/jest": "^30.0.0",
70
177
  "@types/node": "^20.19.33",
178
+ "express": "^5.2.1",
71
179
  "jest": "^30.3.0",
72
180
  "secretlint": "^13.0.5",
73
181
  "ts-jest": "^29.4.9",
74
- "typescript": "^5.9.3"
182
+ "tsx": "^4.20.0",
183
+ "typescript": "^5.9.3",
184
+ "zod": "^4.2.0"
75
185
  },
76
186
  "engines": {
77
- "node": ">=18.0.0"
187
+ "node": ">=20.12.0"
78
188
  },
79
189
  "files": [
80
- "dist"
190
+ "dist",
191
+ "bin",
192
+ "docs",
193
+ "examples"
81
194
  ],
82
195
  "scripts": {
83
196
  "build": "tsc",
84
- "typecheck": "tsc --noEmit",
85
- "test": "node scripts/run-jest.mjs --runInBand",
86
- "test:watch": "node scripts/run-jest.mjs --watch",
87
- "test:coverage": "node scripts/run-jest.mjs --runInBand --coverage",
88
- "lint": "biome check src tests scripts",
89
- "format": "biome check --write src tests scripts",
197
+ "typecheck": "tsc --noEmit && tsc --noEmit -p tsconfig.examples.json",
198
+ "test": "node bin/mcp-core-jest.mjs --runInBand",
199
+ "test:watch": "node bin/mcp-core-jest.mjs --watch",
200
+ "test:coverage": "node bin/mcp-core-jest.mjs --runInBand --coverage",
201
+ "lint": "biome check src tests scripts bin examples",
202
+ "format": "biome check --write src tests scripts bin examples",
90
203
  "secretlint": "secretlint \"**/*\" --secretlintignore .gitignore",
91
204
  "docs:check": "node scripts/check-docs-freshness.mjs",
92
205
  "qa:all": "node scripts/qa-all.mjs",
package/dist/logger.d.ts DELETED
@@ -1,80 +0,0 @@
1
- /**
2
- * @novorb/mcp-core — Logger
3
- *
4
- * Unified logger for MCP servers. Supports two output modes:
5
- * - file: writes to rotating log files (for stdio-based MCP servers)
6
- * - stderr: writes to stderr (for Docker / HTTP transport)
7
- *
8
- * Log format (text): 2026-03-22T13:27:58.513Z | INFO | Server | Starting...
9
- * Log format (json): {"level":"INFO","timestamp":"...","component":"Server","message":"Starting..."}
10
- *
11
- * Environment variables (read once at first logger creation):
12
- * - LOG_LEVEL: DEBUG, INFO, WARN, ERROR (default: INFO)
13
- * - LOG_PATH: log directory (default: ./logs)
14
- * - LOG_FILE: log file name (default: mcp.log)
15
- *
16
- * Security: `meta` is passed through `redactSecrets()` before serialisation — sensitive-keyed fields
17
- * (authorization/token/api_key/secret/password/cookie/...) are replaced with `[REDACTED]` so a
18
- * consumer that logs an error object or request params never writes a credential in cleartext. In
19
- * text mode the message + component are also stripped of CR/LF so a logged value can't forge log lines.
20
- */
21
- export declare enum LogLevel {
22
- DEBUG = 0,
23
- INFO = 1,
24
- WARN = 2,
25
- ERROR = 3
26
- }
27
- export interface LoggerConfig {
28
- /** Minimum log level (default: INFO) */
29
- level: LogLevel;
30
- /** Output mode: 'file' writes to disk, 'stderr' writes to process.stderr */
31
- output: 'file' | 'stderr';
32
- /** Format: 'text' for human-readable, 'json' for structured (default: text) */
33
- format: 'text' | 'json';
34
- /** Directory for log files (file mode only) */
35
- logDir: string;
36
- /** Log file name (file mode only, default: mcp.log) */
37
- logFile: string;
38
- /** Max log file size in bytes before rotation (default: 10MB) */
39
- maxLogSize: number;
40
- /** Max number of rotated log files to keep (default: 5) */
41
- maxLogFiles: number;
42
- }
43
- /** Recursively copy a value, replacing any sensitive-keyed field with `[REDACTED]`. */
44
- export declare function redactSecrets(value: unknown, depth?: number): unknown;
45
- export declare class Logger {
46
- private config;
47
- private logPath;
48
- constructor(config?: Partial<LoggerConfig>);
49
- private ensureLogDirectory;
50
- private shouldLog;
51
- private formatText;
52
- private formatJson;
53
- private format;
54
- private write;
55
- private writeToFile;
56
- private rotateLog;
57
- debug(message: string, context?: string, meta?: unknown): void;
58
- info(message: string, context?: string, meta?: unknown): void;
59
- warn(message: string, context?: string, meta?: unknown): void;
60
- error(message: string, context?: string, meta?: unknown): void;
61
- setLevel(level: LogLevel): void;
62
- }
63
- /**
64
- * Initialize logger with custom config.
65
- * Should be called once at application startup.
66
- * Reads LOG_LEVEL, LOG_PATH, LOG_FILE from env (overrides take precedence).
67
- */
68
- export declare function initLogger(config?: Partial<LoggerConfig>): Logger;
69
- /**
70
- * Get the logger instance.
71
- * Creates a default stderr/text instance if initLogger was not called.
72
- * Reads LOG_LEVEL, LOG_PATH, LOG_FILE from env on first creation.
73
- */
74
- export declare function getLogger(config?: Partial<LoggerConfig>): Logger;
75
- /**
76
- * Reset the singleton (for testing).
77
- */
78
- export declare function resetLogger(): void;
79
- export default getLogger;
80
- //# sourceMappingURL=logger.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAKH,oBAAY,QAAQ;IAClB,KAAK,IAAI;IACT,IAAI,IAAI;IACR,IAAI,IAAI;IACR,KAAK,IAAI;CACV;AAaD,MAAM,WAAW,YAAY;IAC3B,wCAAwC;IACxC,KAAK,EAAE,QAAQ,CAAC;IAChB,4EAA4E;IAC5E,MAAM,EAAE,MAAM,GAAG,QAAQ,CAAC;IAC1B,+EAA+E;IAC/E,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB,+CAA+C;IAC/C,MAAM,EAAE,MAAM,CAAC;IACf,uDAAuD;IACvD,OAAO,EAAE,MAAM,CAAC;IAChB,iEAAiE;IACjE,UAAU,EAAE,MAAM,CAAC;IACnB,2DAA2D;IAC3D,WAAW,EAAE,MAAM,CAAC;CACrB;AAkCD,uFAAuF;AACvF,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,SAAI,GAAG,OAAO,CAQhE;AAoBD,qBAAa,MAAM;IACjB,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,OAAO,CAAS;gBAEZ,MAAM,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC;IAS1C,OAAO,CAAC,kBAAkB;IAM1B,OAAO,CAAC,SAAS;IAIjB,OAAO,CAAC,UAAU;IASlB,OAAO,CAAC,UAAU;IAkBlB,OAAO,CAAC,MAAM;IAMd,OAAO,CAAC,KAAK;IAYb,OAAO,CAAC,WAAW;IAcnB,OAAO,CAAC,SAAS;IAqBjB,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI;IAI9D,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI;IAI7D,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI;IAI7D,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI;IAI9D,QAAQ,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI;CAGhC;AAKD;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG,MAAM,CAGjE;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG,MAAM,CAKhE;AAED;;GAEG;AACH,wBAAgB,WAAW,IAAI,IAAI,CAElC;AAED,eAAe,SAAS,CAAC"}
package/dist/logger.js DELETED
@@ -1,237 +0,0 @@
1
- /**
2
- * @novorb/mcp-core — Logger
3
- *
4
- * Unified logger for MCP servers. Supports two output modes:
5
- * - file: writes to rotating log files (for stdio-based MCP servers)
6
- * - stderr: writes to stderr (for Docker / HTTP transport)
7
- *
8
- * Log format (text): 2026-03-22T13:27:58.513Z | INFO | Server | Starting...
9
- * Log format (json): {"level":"INFO","timestamp":"...","component":"Server","message":"Starting..."}
10
- *
11
- * Environment variables (read once at first logger creation):
12
- * - LOG_LEVEL: DEBUG, INFO, WARN, ERROR (default: INFO)
13
- * - LOG_PATH: log directory (default: ./logs)
14
- * - LOG_FILE: log file name (default: mcp.log)
15
- *
16
- * Security: `meta` is passed through `redactSecrets()` before serialisation — sensitive-keyed fields
17
- * (authorization/token/api_key/secret/password/cookie/...) are replaced with `[REDACTED]` so a
18
- * consumer that logs an error object or request params never writes a credential in cleartext. In
19
- * text mode the message + component are also stripped of CR/LF so a logged value can't forge log lines.
20
- */
21
- import * as fs from 'node:fs';
22
- import * as path from 'node:path';
23
- export var LogLevel;
24
- (function (LogLevel) {
25
- LogLevel[LogLevel["DEBUG"] = 0] = "DEBUG";
26
- LogLevel[LogLevel["INFO"] = 1] = "INFO";
27
- LogLevel[LogLevel["WARN"] = 2] = "WARN";
28
- LogLevel[LogLevel["ERROR"] = 3] = "ERROR";
29
- })(LogLevel || (LogLevel = {}));
30
- /** Map string → LogLevel, case-insensitive */
31
- function parseLogLevel(value) {
32
- if (!value)
33
- return undefined;
34
- const upper = value.toUpperCase();
35
- const byName = LogLevel;
36
- if (upper in LogLevel && typeof byName[upper] === 'number') {
37
- return byName[upper];
38
- }
39
- return undefined;
40
- }
41
- const DEFAULT_CONFIG = {
42
- level: LogLevel.INFO,
43
- output: 'stderr',
44
- format: 'text',
45
- logDir: 'logs',
46
- logFile: 'mcp.log',
47
- maxLogSize: 10 * 1024 * 1024,
48
- maxLogFiles: 5,
49
- };
50
- /** Build config from defaults + env vars + explicit overrides */
51
- function buildConfig(overrides) {
52
- const envLevel = parseLogLevel(process.env.LOG_LEVEL);
53
- const envDir = process.env.LOG_PATH;
54
- const envFile = process.env.LOG_FILE;
55
- return {
56
- ...DEFAULT_CONFIG,
57
- ...(envLevel !== undefined ? { level: envLevel } : {}),
58
- ...(envDir ? { logDir: envDir } : {}),
59
- ...(envFile ? { logFile: envFile } : {}),
60
- ...overrides,
61
- };
62
- }
63
- // Keys whose values are redacted before a `meta` object is serialised. Defense-in-depth: consumers
64
- // commonly pass error objects / request params carrying credentials, and a log sink must never write
65
- // them in cleartext. Matched case-insensitively against each object key.
66
- const SENSITIVE_KEY = /(authorization|cookie|password|secret|client[_-]?secret|access[_-]?token|refresh[_-]?token|token|api[_-]?key|apikey|bearer|private[_-]?key|signature|x-api-key)/i;
67
- const REDACTED = '[REDACTED]';
68
- /** Recursively copy a value, replacing any sensitive-keyed field with `[REDACTED]`. */
69
- export function redactSecrets(value, depth = 0) {
70
- if (depth > 6 || value === null || typeof value !== 'object')
71
- return value;
72
- if (Array.isArray(value))
73
- return value.map((v) => redactSecrets(v, depth + 1));
74
- const out = {};
75
- for (const [k, v] of Object.entries(value)) {
76
- out[k] = SENSITIVE_KEY.test(k) ? REDACTED : redactSecrets(v, depth + 1);
77
- }
78
- return out;
79
- }
80
- /** Collapse C0 control chars (incl. CR/LF) + DEL to spaces so a logged value can't forge log lines. */
81
- function stripControlChars(s) {
82
- let out = '';
83
- for (let i = 0; i < s.length; i++) {
84
- const code = s.charCodeAt(i);
85
- out += code < 0x20 || code === 0x7f ? ' ' : s[i];
86
- }
87
- return out;
88
- }
89
- // Padded level names — fixed 5 chars for alignment
90
- const LEVEL_NAMES = {
91
- [LogLevel.DEBUG]: 'DEBUG',
92
- [LogLevel.INFO]: 'INFO ',
93
- [LogLevel.WARN]: 'WARN ',
94
- [LogLevel.ERROR]: 'ERROR',
95
- };
96
- export class Logger {
97
- config;
98
- logPath;
99
- constructor(config) {
100
- this.config = buildConfig(config);
101
- this.logPath = path.join(this.config.logDir, this.config.logFile);
102
- if (this.config.output === 'file') {
103
- this.ensureLogDirectory();
104
- }
105
- }
106
- ensureLogDirectory() {
107
- if (!fs.existsSync(this.config.logDir)) {
108
- fs.mkdirSync(this.config.logDir, { recursive: true });
109
- }
110
- }
111
- shouldLog(level) {
112
- return level >= this.config.level;
113
- }
114
- formatText(level, message, context, meta) {
115
- const timestamp = new Date().toISOString();
116
- const levelStr = LEVEL_NAMES[level] ?? LogLevel[level].padEnd(5);
117
- const contextStr = stripControlChars(context ?? 'General');
118
- const safeMessage = stripControlChars(message);
119
- const metaStr = meta !== undefined ? ` | ${JSON.stringify(redactSecrets(meta))}` : '';
120
- return `${timestamp} | ${levelStr} | ${contextStr} | ${safeMessage}${metaStr}\n`;
121
- }
122
- formatJson(level, message, context, meta) {
123
- const entry = {
124
- level: LogLevel[level],
125
- timestamp: new Date().toISOString(),
126
- component: context ?? 'General',
127
- message,
128
- };
129
- if (meta !== undefined) {
130
- const safeMeta = redactSecrets(meta);
131
- if (typeof safeMeta === 'object' && safeMeta !== null) {
132
- Object.assign(entry, safeMeta);
133
- }
134
- else {
135
- entry.meta = safeMeta;
136
- }
137
- }
138
- return `${JSON.stringify(entry)}\n`;
139
- }
140
- format(level, message, context, meta) {
141
- return this.config.format === 'json'
142
- ? this.formatJson(level, message, context, meta)
143
- : this.formatText(level, message, context, meta);
144
- }
145
- write(level, message, context, meta) {
146
- if (!this.shouldLog(level))
147
- return;
148
- const formatted = this.format(level, message, context, meta);
149
- if (this.config.output === 'file') {
150
- this.writeToFile(formatted);
151
- }
152
- else {
153
- process.stderr.write(formatted);
154
- }
155
- }
156
- writeToFile(message) {
157
- try {
158
- if (fs.existsSync(this.logPath)) {
159
- const stats = fs.statSync(this.logPath);
160
- if (stats.size > this.config.maxLogSize) {
161
- this.rotateLog();
162
- }
163
- }
164
- fs.appendFileSync(this.logPath, message, 'utf8');
165
- }
166
- catch {
167
- // Silently fail — can't log to console in MCP stdio context
168
- }
169
- }
170
- rotateLog() {
171
- try {
172
- for (let i = this.config.maxLogFiles - 1; i > 0; i--) {
173
- const oldPath = `${this.logPath}.${i}`;
174
- const newPath = `${this.logPath}.${i + 1}`;
175
- if (fs.existsSync(oldPath)) {
176
- if (i === this.config.maxLogFiles - 1) {
177
- fs.unlinkSync(oldPath);
178
- }
179
- else {
180
- fs.renameSync(oldPath, newPath);
181
- }
182
- }
183
- }
184
- if (fs.existsSync(this.logPath)) {
185
- fs.renameSync(this.logPath, `${this.logPath}.1`);
186
- }
187
- }
188
- catch {
189
- // Silently fail
190
- }
191
- }
192
- debug(message, context, meta) {
193
- this.write(LogLevel.DEBUG, message, context, meta);
194
- }
195
- info(message, context, meta) {
196
- this.write(LogLevel.INFO, message, context, meta);
197
- }
198
- warn(message, context, meta) {
199
- this.write(LogLevel.WARN, message, context, meta);
200
- }
201
- error(message, context, meta) {
202
- this.write(LogLevel.ERROR, message, context, meta);
203
- }
204
- setLevel(level) {
205
- this.config.level = level;
206
- }
207
- }
208
- // Singleton management
209
- let loggerInstance = null;
210
- /**
211
- * Initialize logger with custom config.
212
- * Should be called once at application startup.
213
- * Reads LOG_LEVEL, LOG_PATH, LOG_FILE from env (overrides take precedence).
214
- */
215
- export function initLogger(config) {
216
- loggerInstance = new Logger(config);
217
- return loggerInstance;
218
- }
219
- /**
220
- * Get the logger instance.
221
- * Creates a default stderr/text instance if initLogger was not called.
222
- * Reads LOG_LEVEL, LOG_PATH, LOG_FILE from env on first creation.
223
- */
224
- export function getLogger(config) {
225
- if (!loggerInstance) {
226
- loggerInstance = new Logger(config);
227
- }
228
- return loggerInstance;
229
- }
230
- /**
231
- * Reset the singleton (for testing).
232
- */
233
- export function resetLogger() {
234
- loggerInstance = null;
235
- }
236
- export default getLogger;
237
- //# sourceMappingURL=logger.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"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"}