@novorb/mcp-core 2.1.0

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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Novorb
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,179 @@
1
+ # NOVORB - MCP Core
2
+
3
+ ---
4
+
5
+ [![npm](https://img.shields.io/badge/%40novorb%2Fmcp--core-2.1.0-blue)](https://www.npmjs.com/package/@novorb/mcp-core)
6
+ [![Node](https://img.shields.io/badge/Node-22%2B-green)](https://nodejs.org/)
7
+ [![Tests](https://img.shields.io/badge/Tests-98-purple)]()
8
+ [![License](https://img.shields.io/badge/License-MIT-yellow)](LICENSE)
9
+
10
+ Shared TypeScript utilities for building MCP (Model Context Protocol) servers — logging, HTTP clients, retry logic, pagination, and transport — so every MCP server gets a consistent, tested foundation without reimplementing common patterns.
11
+
12
+ ## Features
13
+
14
+ - **Structured logging** — file output with rotation, stderr output, text or JSON format, secret redaction
15
+ - **HTTP client** — axios wrapper with automatic retry on 429/5xx, request logging, pagination
16
+ - **Retry with backoff** — exponential backoff with jitter, configurable retries and delays
17
+ - **Pagination helpers** — normalize params, compute metadata, paginate arrays in memory
18
+ - **Unified transport** — stdio and stateless streamable-HTTP with built-in auth and DNS-rebinding protection
19
+ - **Server builder** — `McpServer` factory, annotation presets, and SDK re-exports from one import point
20
+ - **ESM native** — built as ES modules with full TypeScript declarations
21
+
22
+ ## Documentation
23
+
24
+ - **[CLAUDE.md](CLAUDE.md)** — agent/contributor context and working conventions
25
+ - **[docs/TESTING.md](docs/TESTING.md)** — test runner commands, conventions, and guidelines
26
+
27
+ ## Installation
28
+
29
+ ```bash
30
+ npm install @novorb/mcp-core
31
+ ```
32
+
33
+ ## Modules
34
+
35
+ ### Logger
36
+
37
+ Unified logger supporting file output (with rotation) and stderr output, in text or structured JSON format. MCP servers use stdio for protocol communication, so logging to stdout/stderr directly isn't always possible — file-based logging solves this. Sensitive-keyed fields in `meta` are redacted before serialisation.
38
+
39
+ ```typescript
40
+ import { initLogger, LogLevel } from '@novorb/mcp-core';
41
+
42
+ // File-based (writes to logs/mcp.log with rotation)
43
+ const logger = initLogger({
44
+ output: 'file',
45
+ logDir: './logs',
46
+ level: LogLevel.INFO,
47
+ });
48
+
49
+ // Stderr with structured JSON
50
+ const logger = initLogger({
51
+ output: 'stderr',
52
+ format: 'json',
53
+ });
54
+
55
+ logger.info('Server started', 'Server');
56
+ logger.error('Request failed', 'HttpClient', { status: 500, path: '/api/items' });
57
+ ```
58
+
59
+ ### HTTP Client
60
+
61
+ Pre-configured axios wrapper with automatic retry on transient failures (429, 5xx, network errors) for idempotent methods, request/response logging, and pagination support via `X-Total-Count` headers.
62
+
63
+ ```typescript
64
+ import { createHttpClient } from '@novorb/mcp-core';
65
+
66
+ const client = createHttpClient({
67
+ baseURL: 'https://api.example.com',
68
+ headers: { 'Authorization': 'Bearer token' },
69
+ retries: 3,
70
+ logContext: 'MyApiClient',
71
+ });
72
+
73
+ const item = await client.get('/items/1');
74
+ const { data, totalCount } = await client.getPaginated('/items', { page: 1, per_page: 50 });
75
+ await client.post('/items', { name: 'new item' });
76
+ ```
77
+
78
+ ### Retry
79
+
80
+ Exponential backoff with jitter for retrying failed operations. Used internally by the HTTP client, but also available standalone.
81
+
82
+ ```typescript
83
+ import { retryWithBackoff, isRetryableError } from '@novorb/mcp-core';
84
+
85
+ const result = await retryWithBackoff(async (ctx) => {
86
+ console.log(`Attempt ${ctx.attempt + 1}/${ctx.maxRetries + 1}`);
87
+ return await someUnreliableOperation();
88
+ }, {
89
+ maxRetries: 3,
90
+ initialDelayMs: 1000,
91
+ backoffMultiplier: 2,
92
+ });
93
+ ```
94
+
95
+ ### Pagination
96
+
97
+ Normalize pagination parameters, compute metadata, and paginate arrays in memory.
98
+
99
+ ```typescript
100
+ import { normalizePagination, createPaginationMetadata, paginateArray } from '@novorb/mcp-core';
101
+
102
+ const params = normalizePagination({ page: 3, per_page: 200 });
103
+ // { page: 3, per_page: 100 } (capped at max)
104
+
105
+ const metadata = createPaginationMetadata(500, params);
106
+ // { totalCount: 500, page: 3, perPage: 100, totalPages: 5 }
107
+
108
+ const { data, metadata } = paginateArray(allItems, { page: 2, per_page: 20 });
109
+ ```
110
+
111
+ ### Transport
112
+
113
+ Unified transport that selects between stdio and stateless streamable HTTP based on the `MCP_TRANSPORT` environment variable. HTTP mode is fail-closed (refuses to start without auth unless explicitly disabled) and supports Bearer-token auth, body-size caps, and opt-in DNS-rebinding protection.
114
+
115
+ ```typescript
116
+ import { startMcpServer } from '@novorb/mcp-core/transport';
117
+
118
+ // Factory (recommended for HTTP — fresh server instance per request):
119
+ await startMcpServer(() => createServer(services));
120
+
121
+ // Server instance (fine for stdio):
122
+ await startMcpServer(server);
123
+ ```
124
+
125
+ | Variable | Default | Description |
126
+ |----------|---------|-------------|
127
+ | `MCP_TRANSPORT` | `stdio` | Transport mode: `stdio` or `http` |
128
+ | `PORT` | `8080` | HTTP listen port |
129
+ | `MCP_HTTP_HOST` | `0.0.0.0` | Bind address (`127.0.0.1` for local-only) |
130
+ | `MCP_API_KEY` | none | Bearer token for HTTP auth (required in HTTP mode unless disabled) |
131
+ | `MCP_AUTH_DISABLED` | `false` | Set `true` to run HTTP without auth (only behind a fronting gateway) |
132
+ | `MCP_MAX_BODY_BYTES` | 4 MiB | Max accepted POST body size |
133
+ | `MCP_ALLOWED_HOSTS` | none | Comma-separated Host allowlist (enables DNS-rebinding protection) |
134
+ | `MCP_ALLOWED_ORIGINS` | none | Comma-separated Origin allowlist (enables DNS-rebinding protection) |
135
+
136
+ ### Server
137
+
138
+ Import MCP server-building primitives from here instead of the SDK directly, to centralise the MCP dependency.
139
+
140
+ ```typescript
141
+ import { createMcpServer, TOOL_ANNOTATIONS, completable } from '@novorb/mcp-core/server';
142
+ import type { McpToolAnnotations, McpCallToolResult } from '@novorb/mcp-core/server';
143
+
144
+ const server = createMcpServer('my-mcp', '1.0.0');
145
+
146
+ server.registerTool('lookup', {
147
+ description: 'Look up a value',
148
+ inputSchema: { key: z.string() },
149
+ outputSchema: { value: z.string(), found: z.boolean() },
150
+ annotations: TOOL_ANNOTATIONS.readOnly,
151
+ }, async ({ key }) => ({
152
+ content: [{ type: 'text', text: value }],
153
+ structuredContent: { value, found: true },
154
+ }));
155
+ ```
156
+
157
+ **`TOOL_ANNOTATIONS` presets:** `readOnly` (lookups/searches), `idempotentWrite` (upserts), `mutableWrite` (non-idempotent writes), `destructive` (deletes/overwrites).
158
+
159
+ ## Testing
160
+
161
+ ```bash
162
+ npm test # 67 tests
163
+ npm run test:watch # watch mode
164
+ npm run test:coverage
165
+ ```
166
+
167
+ > **Windows note:** the test scripts set `NODE_OPTIONS=` inline, which is Unix shell syntax. On Windows, invoke jest directly via a bash shell. See [docs/TESTING.md](docs/TESTING.md).
168
+
169
+ ## Building
170
+
171
+ ```bash
172
+ npm run build # tsc → dist/
173
+ ```
174
+
175
+ This is an ESM package (`"type": "module"`). `tsconfig.json` is self-contained so it builds standalone.
176
+
177
+ ## License
178
+
179
+ [MIT](LICENSE)
@@ -0,0 +1,69 @@
1
+ /**
2
+ * @novorb/mcp-core — HTTP Client Factory
3
+ *
4
+ * Creates pre-configured axios instances with retry logic and logging.
5
+ */
6
+ import { AxiosInstance } from 'axios';
7
+ import { Logger } from './logger.js';
8
+ export interface HttpClientConfig {
9
+ /** Base URL for all requests */
10
+ baseURL: string;
11
+ /** Request timeout in milliseconds (default: 30000) */
12
+ timeout?: number;
13
+ /** Default headers to include on every request */
14
+ headers?: Record<string, string>;
15
+ /** Number of retries on retryable failures (default: 3) */
16
+ retries?: number;
17
+ /** Logger instance (default: singleton from getLogger) */
18
+ logger?: Logger;
19
+ /** Component name for log messages (default: 'HttpClient') */
20
+ logContext?: string;
21
+ }
22
+ export interface PaginatedResponse<T> {
23
+ data: T[];
24
+ totalCount: number;
25
+ }
26
+ /**
27
+ * MCP HTTP client wrapping axios with retry, logging, and pagination support.
28
+ */
29
+ export declare class McpHttpClient {
30
+ private client;
31
+ private logger;
32
+ private logContext;
33
+ constructor(config: HttpClientConfig);
34
+ /**
35
+ * Perform a GET request.
36
+ */
37
+ get<T>(path: string, params?: Record<string, unknown>): Promise<T>;
38
+ /**
39
+ * Perform a GET request with pagination.
40
+ * Reads total count from the X-Total-Count response header.
41
+ */
42
+ getPaginated<T>(path: string, params?: Record<string, unknown>): Promise<PaginatedResponse<T>>;
43
+ /**
44
+ * Perform a POST request.
45
+ */
46
+ post<T>(path: string, data?: unknown, params?: Record<string, unknown>): Promise<T>;
47
+ /**
48
+ * Perform a PUT request.
49
+ */
50
+ put<T>(path: string, data?: unknown, params?: Record<string, unknown>): Promise<T>;
51
+ /**
52
+ * Perform a PATCH request.
53
+ */
54
+ patch<T>(path: string, data?: unknown, params?: Record<string, unknown>): Promise<T>;
55
+ /**
56
+ * Perform a DELETE request.
57
+ */
58
+ delete<T>(path: string, params?: Record<string, unknown>): Promise<T>;
59
+ /**
60
+ * Get the underlying axios instance for advanced use cases.
61
+ */
62
+ getAxiosInstance(): AxiosInstance;
63
+ private normalizeError;
64
+ }
65
+ /**
66
+ * Create a configured HTTP client.
67
+ */
68
+ export declare function createHttpClient(config: HttpClientConfig): McpHttpClient;
69
+ //# sourceMappingURL=http-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-client.d.ts","sourceRoot":"","sources":["../src/http-client.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAc,EAAE,aAAa,EAAc,MAAM,OAAO,CAAC;AAEzD,OAAO,EAAa,MAAM,EAAE,MAAM,aAAa,CAAC;AAEhD,MAAM,WAAW,gBAAgB;IAC/B,gCAAgC;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,uDAAuD;IACvD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,kDAAkD;IAClD,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,2DAA2D;IAC3D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,0DAA0D;IAC1D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,8DAA8D;IAC9D,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,iBAAiB,CAAC,CAAC;IAClC,IAAI,EAAE,CAAC,EAAE,CAAC;IACV,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,UAAU,CAAS;gBAEf,MAAM,EAAE,gBAAgB;IAmCpC;;OAEG;IACG,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAsBxE;;;OAGG;IACG,YAAY,CAAC,CAAC,EAClB,IAAI,EAAE,MAAM,EACZ,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC;IAyBhC;;OAEG;IACG,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAsBzF;;OAEG;IACG,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAsBxF;;OAEG;IACG,KAAK,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAsB1F;;OAEG;IACG,MAAM,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAsB3E;;OAEG;IACH,gBAAgB,IAAI,aAAa;IAIjC,OAAO,CAAC,cAAc;CAkBvB;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,gBAAgB,GAAG,aAAa,CAExE"}
@@ -0,0 +1,228 @@
1
+ /**
2
+ * @novorb/mcp-core — HTTP Client Factory
3
+ *
4
+ * Creates pre-configured axios instances with retry logic and logging.
5
+ */
6
+ import axios from 'axios';
7
+ import axiosRetry from 'axios-retry';
8
+ import { getLogger } from './logger.js';
9
+ /**
10
+ * MCP HTTP client wrapping axios with retry, logging, and pagination support.
11
+ */
12
+ export class McpHttpClient {
13
+ client;
14
+ logger;
15
+ logContext;
16
+ constructor(config) {
17
+ this.logger = config.logger || getLogger();
18
+ this.logContext = config.logContext || 'HttpClient';
19
+ this.client = axios.create({
20
+ baseURL: config.baseURL,
21
+ timeout: config.timeout || 30000,
22
+ // Never follow redirects: the instance carries a static Authorization header, and axios re-sends
23
+ // request data to a 3xx Location — a malicious/compromised upstream could harvest the credential.
24
+ maxRedirects: 0,
25
+ // Cap response/request size (OOM/DoS guard).
26
+ maxContentLength: 25 * 1024 * 1024,
27
+ maxBodyLength: 25 * 1024 * 1024,
28
+ headers: {
29
+ 'Content-Type': 'application/json',
30
+ ...config.headers,
31
+ },
32
+ });
33
+ axiosRetry(this.client, {
34
+ retries: config.retries ?? 3,
35
+ retryDelay: axiosRetry.exponentialDelay,
36
+ retryCondition: (error) => {
37
+ // Network/idempotent-request errors are already method-safe. Only ALSO retry 429/5xx for
38
+ // idempotent methods — never replay a non-idempotent POST/PATCH (duplicate side effects).
39
+ if (axiosRetry.isNetworkOrIdempotentRequestError(error))
40
+ return true;
41
+ const method = (error.config?.method ?? 'get').toLowerCase();
42
+ const idempotent = ['get', 'head', 'options', 'put', 'delete'].includes(method);
43
+ const status = error.response?.status;
44
+ const retryableStatus = status === 429 || (status !== undefined && status >= 500);
45
+ return idempotent && retryableStatus;
46
+ },
47
+ });
48
+ }
49
+ /**
50
+ * Perform a GET request.
51
+ */
52
+ async get(path, params) {
53
+ const startTime = Date.now();
54
+ this.logger.debug(`GET ${path}`, this.logContext, { params });
55
+ try {
56
+ const response = await this.client.get(path, { params });
57
+ const duration = Date.now() - startTime;
58
+ this.logger.debug(`GET ${path} completed`, this.logContext, {
59
+ status: response.status,
60
+ duration: `${duration}ms`,
61
+ });
62
+ return response.data;
63
+ }
64
+ catch (error) {
65
+ const duration = Date.now() - startTime;
66
+ this.logger.error(`GET ${path} failed`, this.logContext, {
67
+ duration: `${duration}ms`,
68
+ error: error instanceof Error ? error.message : String(error),
69
+ });
70
+ throw this.normalizeError(error);
71
+ }
72
+ }
73
+ /**
74
+ * Perform a GET request with pagination.
75
+ * Reads total count from the X-Total-Count response header.
76
+ */
77
+ async getPaginated(path, params) {
78
+ const startTime = Date.now();
79
+ this.logger.debug(`GET (paginated) ${path}`, this.logContext, { params });
80
+ try {
81
+ const response = await this.client.get(path, { params });
82
+ const totalCount = parseInt(response.headers['x-total-count'] || '0', 10);
83
+ const duration = Date.now() - startTime;
84
+ this.logger.debug(`GET (paginated) ${path} completed`, this.logContext, {
85
+ status: response.status,
86
+ totalCount,
87
+ resultCount: response.data.length,
88
+ duration: `${duration}ms`,
89
+ });
90
+ return { data: response.data, totalCount };
91
+ }
92
+ catch (error) {
93
+ const duration = Date.now() - startTime;
94
+ this.logger.error(`GET (paginated) ${path} failed`, this.logContext, {
95
+ duration: `${duration}ms`,
96
+ error: error instanceof Error ? error.message : String(error),
97
+ });
98
+ throw this.normalizeError(error);
99
+ }
100
+ }
101
+ /**
102
+ * Perform a POST request.
103
+ */
104
+ async post(path, data, params) {
105
+ const startTime = Date.now();
106
+ this.logger.debug(`POST ${path}`, this.logContext);
107
+ try {
108
+ const response = await this.client.post(path, data, { params });
109
+ const duration = Date.now() - startTime;
110
+ this.logger.debug(`POST ${path} completed`, this.logContext, {
111
+ status: response.status,
112
+ duration: `${duration}ms`,
113
+ });
114
+ return response.data;
115
+ }
116
+ catch (error) {
117
+ const duration = Date.now() - startTime;
118
+ this.logger.error(`POST ${path} failed`, this.logContext, {
119
+ duration: `${duration}ms`,
120
+ error: error instanceof Error ? error.message : String(error),
121
+ });
122
+ throw this.normalizeError(error);
123
+ }
124
+ }
125
+ /**
126
+ * Perform a PUT request.
127
+ */
128
+ async put(path, data, params) {
129
+ const startTime = Date.now();
130
+ this.logger.debug(`PUT ${path}`, this.logContext);
131
+ try {
132
+ const response = await this.client.put(path, data, { params });
133
+ const duration = Date.now() - startTime;
134
+ this.logger.debug(`PUT ${path} completed`, this.logContext, {
135
+ status: response.status,
136
+ duration: `${duration}ms`,
137
+ });
138
+ return response.data;
139
+ }
140
+ catch (error) {
141
+ const duration = Date.now() - startTime;
142
+ this.logger.error(`PUT ${path} failed`, this.logContext, {
143
+ duration: `${duration}ms`,
144
+ error: error instanceof Error ? error.message : String(error),
145
+ });
146
+ throw this.normalizeError(error);
147
+ }
148
+ }
149
+ /**
150
+ * Perform a PATCH request.
151
+ */
152
+ async patch(path, data, params) {
153
+ const startTime = Date.now();
154
+ this.logger.debug(`PATCH ${path}`, this.logContext);
155
+ try {
156
+ const response = await this.client.patch(path, data, { params });
157
+ const duration = Date.now() - startTime;
158
+ this.logger.debug(`PATCH ${path} completed`, this.logContext, {
159
+ status: response.status,
160
+ duration: `${duration}ms`,
161
+ });
162
+ return response.data;
163
+ }
164
+ catch (error) {
165
+ const duration = Date.now() - startTime;
166
+ this.logger.error(`PATCH ${path} failed`, this.logContext, {
167
+ duration: `${duration}ms`,
168
+ error: error instanceof Error ? error.message : String(error),
169
+ });
170
+ throw this.normalizeError(error);
171
+ }
172
+ }
173
+ /**
174
+ * Perform a DELETE request.
175
+ */
176
+ async delete(path, params) {
177
+ const startTime = Date.now();
178
+ this.logger.debug(`DELETE ${path}`, this.logContext);
179
+ try {
180
+ const response = await this.client.delete(path, { params });
181
+ const duration = Date.now() - startTime;
182
+ this.logger.debug(`DELETE ${path} completed`, this.logContext, {
183
+ status: response.status,
184
+ duration: `${duration}ms`,
185
+ });
186
+ return response.data;
187
+ }
188
+ catch (error) {
189
+ const duration = Date.now() - startTime;
190
+ this.logger.error(`DELETE ${path} failed`, this.logContext, {
191
+ duration: `${duration}ms`,
192
+ error: error instanceof Error ? error.message : String(error),
193
+ });
194
+ throw this.normalizeError(error);
195
+ }
196
+ }
197
+ /**
198
+ * Get the underlying axios instance for advanced use cases.
199
+ */
200
+ getAxiosInstance() {
201
+ return this.client;
202
+ }
203
+ normalizeError(error) {
204
+ if (axios.isAxiosError(error)) {
205
+ const status = error.response?.status;
206
+ const statusText = error.response?.statusText;
207
+ const data = error.response?.data;
208
+ const message = typeof data === 'object' && data?.message
209
+ ? data.message
210
+ : `HTTP ${status} ${statusText}`;
211
+ const normalized = new Error(message);
212
+ // Attach only the status — NOT the raw axios `response`. Its `config` carries the request's
213
+ // Authorization header/token, and the upstream response headers may carry set-cookie/auth
214
+ // echoes; a consumer logging the thrown error would otherwise leak them.
215
+ normalized.status = status;
216
+ normalized.statusText = statusText;
217
+ return normalized;
218
+ }
219
+ return error instanceof Error ? error : new Error(String(error));
220
+ }
221
+ }
222
+ /**
223
+ * Create a configured HTTP client.
224
+ */
225
+ export function createHttpClient(config) {
226
+ return new McpHttpClient(config);
227
+ }
228
+ //# sourceMappingURL=http-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-client.js","sourceRoot":"","sources":["../src/http-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * @novorb/mcp-core
3
+ *
4
+ * Shared utilities for MCP servers.
5
+ */
6
+ export { Logger, LogLevel, initLogger, getLogger, resetLogger, type LoggerConfig, } from './logger.js';
7
+ export { retryWithBackoff, calculateRetryDelay, isRetryableError, sleep, parseRetryAfter, type RetryOptions, type RetryContext, } from './retry.js';
8
+ export { normalizePagination, createPaginationMetadata, pageToOffset, paginateArray, type PaginationParams, type NormalizedPagination, type PaginationMetadata, } from './pagination.js';
9
+ export { McpHttpClient, createHttpClient, type HttpClientConfig, type PaginatedResponse, } from './http-client.js';
10
+ export { startMcpServer, type TransportMode, type TransportOptions, } from './transport.js';
11
+ export { McpServer, completable, createMcpServer, TOOL_ANNOTATIONS, type McpToolAnnotations, type McpCallToolResult, } from './server.js';
12
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EACL,MAAM,EACN,QAAQ,EACR,UAAU,EACV,SAAS,EACT,WAAW,EACX,KAAK,YAAY,GAClB,MAAM,aAAa,CAAC;AAGrB,OAAO,EACL,gBAAgB,EAChB,mBAAmB,EACnB,gBAAgB,EAChB,KAAK,EACL,eAAe,EACf,KAAK,YAAY,EACjB,KAAK,YAAY,GAClB,MAAM,YAAY,CAAC;AAGpB,OAAO,EACL,mBAAmB,EACnB,wBAAwB,EACxB,YAAY,EACZ,aAAa,EACb,KAAK,gBAAgB,EACrB,KAAK,oBAAoB,EACzB,KAAK,kBAAkB,GACxB,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EACL,aAAa,EACb,gBAAgB,EAChB,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,GACvB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACL,cAAc,EACd,KAAK,aAAa,EAClB,KAAK,gBAAgB,GACtB,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EACL,SAAS,EACT,WAAW,EACX,eAAe,EACf,gBAAgB,EAChB,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,GACvB,MAAM,aAAa,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,18 @@
1
+ /**
2
+ * @novorb/mcp-core
3
+ *
4
+ * Shared utilities for MCP servers.
5
+ */
6
+ // Logger
7
+ export { Logger, LogLevel, initLogger, getLogger, resetLogger, } from './logger.js';
8
+ // Retry
9
+ export { retryWithBackoff, calculateRetryDelay, isRetryableError, sleep, parseRetryAfter, } from './retry.js';
10
+ // Pagination
11
+ export { normalizePagination, createPaginationMetadata, pageToOffset, paginateArray, } from './pagination.js';
12
+ // HTTP Client
13
+ export { McpHttpClient, createHttpClient, } from './http-client.js';
14
+ // Transport
15
+ export { startMcpServer, } from './transport.js';
16
+ // Server builder (McpServer patterns, re-exports, annotation presets)
17
+ export { McpServer, completable, createMcpServer, TOOL_ANNOTATIONS, } from './server.js';
18
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,SAAS;AACT,OAAO,EACL,MAAM,EACN,QAAQ,EACR,UAAU,EACV,SAAS,EACT,WAAW,GAEZ,MAAM,aAAa,CAAC;AAErB,QAAQ;AACR,OAAO,EACL,gBAAgB,EAChB,mBAAmB,EACnB,gBAAgB,EAChB,KAAK,EACL,eAAe,GAGhB,MAAM,YAAY,CAAC;AAEpB,aAAa;AACb,OAAO,EACL,mBAAmB,EACnB,wBAAwB,EACxB,YAAY,EACZ,aAAa,GAId,MAAM,iBAAiB,CAAC;AAEzB,cAAc;AACd,OAAO,EACL,aAAa,EACb,gBAAgB,GAGjB,MAAM,kBAAkB,CAAC;AAE1B,YAAY;AACZ,OAAO,EACL,cAAc,GAGf,MAAM,gBAAgB,CAAC;AAExB,sEAAsE;AACtE,OAAO,EACL,SAAS,EACT,WAAW,EACX,eAAe,EACf,gBAAgB,GAGjB,MAAM,aAAa,CAAC"}
@@ -0,0 +1,80 @@
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
@@ -0,0 +1 @@
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;AAYD,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;AAiCD,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"}