@novorb/mcp-core 2.1.1 → 3.0.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.
Files changed (240) hide show
  1. package/README.md +82 -161
  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 +278 -43
  44. package/dist/http-client.d.ts.map +1 -1
  45. package/dist/http-client.js +620 -182
  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 +49 -10
  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 -36
  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 +144 -53
  192. package/dist/transport.d.ts.map +1 -1
  193. package/dist/transport.js +305 -122
  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 +140 -18
  237. package/dist/logger.d.ts +0 -80
  238. package/dist/logger.d.ts.map +0 -1
  239. package/dist/logger.js +0 -236
  240. package/dist/logger.js.map +0 -1
package/dist/tools.js ADDED
@@ -0,0 +1,370 @@
1
+ /**
2
+ * @novorb/mcp-core - Tools
3
+ *
4
+ * Register a server's tool definitions on an SDK v2 `McpServer` through `McpServer.registerTool`, so
5
+ * the SDK keeps doing what it does (tools/list from the schemas, input validation, output validation
6
+ * with the era projection, unknown tool = ProtocolError -32602) and mcp-core adds only what it lacks:
7
+ *
8
+ * - one central wrapper per tool: `logToolCall` / `logToolResult` with the duration (shape only,
9
+ * never values);
10
+ * - thrown errors become an `isError` result through `mapError` (default: a safe message, never a
11
+ * stack trace, never a raw error object); a thrown schema error (zod / Standard Schema issues) names
12
+ * the offending fields;
13
+ * - a returned legacy `{ success: false, error }` envelope becomes `isError: true`;
14
+ * - degraded mode: a tool whose `requires` env keys are not configured is still LISTED and answers one
15
+ * uniform error, `<server> is not configured: set <KEYS>`;
16
+ * - `enabled` filters what is registered at all.
17
+ *
18
+ * registerTools(server, [
19
+ * {
20
+ * name: 'lookup',
21
+ * description: 'Look up a value',
22
+ * inputSchema: z.object({ key: z.string() }),
23
+ * annotations: TOOL_ANNOTATIONS.readOnly,
24
+ * requires: ['API_TOKEN'],
25
+ * handler: async ({ key }, ctx) => toolResult(await client.get(key, { signal: ctx.signal })),
26
+ * },
27
+ * ], { env, serverName: 'my-mcp' });
28
+ */
29
+ import { CLIENT_CAPABILITIES_META_KEY, inputRequired, isInputRequiredResult, ProtocolError, ProtocolErrorCode, } from '@modelcontextprotocol/server';
30
+ import { createClientInput, requestEra } from './client-input.js';
31
+ import { attachCredentialMeta, attachCredentialReport, credentialReportBytes, withCredentialsField, } from './credential-report.js';
32
+ import { CredentialScope, NoUsableCredentialError, processCredentials, runWithCredentialScope, } from './credentials.js';
33
+ import { resolveLimits } from './limits.js';
34
+ import { bindToSurface } from './notifications.js';
35
+ import { InvalidCursorError, invalidCursorResult } from './pagination.js';
36
+ import { runWithRequestContext } from './protocol-logging.js';
37
+ import { RequestStateKeyError } from './request-state.js';
38
+ import { declaresPageArgs, decodeToolCursor, enforceResultLimits, handlerArgs, } from './result-limits.js';
39
+ import { requestStateCodecOf } from './server.js';
40
+ import { InvalidPathSegmentError } from './url-path.js';
41
+ import { getLogger, logToolCall, logToolResult, maskSecretValues } from './utils/logger.js';
42
+ import { redactStringSecrets } from './utils/redact.js';
43
+ /** Identity helper that types a definition's handler arguments from its own input schema. */
44
+ export function defineTool(definition) {
45
+ return definition;
46
+ }
47
+ const LIMIT_KEYS = [
48
+ 'MCP_LIST_PAGE_SIZE',
49
+ 'MCP_MAX_RESULT_ITEMS',
50
+ 'MCP_MAX_RESULT_BYTES',
51
+ 'MCP_MAX_TOOL_INPUT_ELEMENTS',
52
+ ];
53
+ /** The response-limit keys as read through the loaded env (env file and defaults included). */
54
+ function limitsEnv(env) {
55
+ const out = {};
56
+ for (const key of LIMIT_KEYS)
57
+ out[key] = env.get(key);
58
+ return out;
59
+ }
60
+ function isPlainObject(value) {
61
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
62
+ }
63
+ /**
64
+ * A success result: the text block is `opts.text`, the string itself, or pretty JSON; a plain object
65
+ * is also sent as `structuredContent` (the spec requires an object there).
66
+ */
67
+ export function toolResult(data, opts = {}) {
68
+ const text = opts.text ?? (typeof data === 'string' ? data : (JSON.stringify(data, null, 2) ?? String(data)));
69
+ const result = { content: [{ type: 'text', text }] };
70
+ if (isPlainObject(data))
71
+ result.structuredContent = data;
72
+ return result;
73
+ }
74
+ /**
75
+ * Text bound for a client in an error: secret query/userinfo/Basic parameters redacted and every
76
+ * registered secret value masked, exactly as the logger does for its lines.
77
+ */
78
+ export function maskClientText(text) {
79
+ return maskSecretValues(redactStringSecrets(text));
80
+ }
81
+ /**
82
+ * An error result (`isError: true`): the message as text, optional details as a second JSON block.
83
+ * Both are passed through `maskClientText`.
84
+ */
85
+ export function toolError(message, details) {
86
+ const content = [{ type: 'text', text: maskClientText(message) }];
87
+ if (details !== undefined)
88
+ content.push({ type: 'text', text: maskClientText(JSON.stringify(details, null, 2)) });
89
+ return { content, isError: true };
90
+ }
91
+ /** Mask every text block of an error result (whatever produced it). */
92
+ function maskErrorResult(result) {
93
+ if (result.isError !== true)
94
+ return result;
95
+ return {
96
+ ...result,
97
+ content: result.content.map((block) => block.type === 'text' ? { ...block, text: maskClientText(block.text) } : block),
98
+ };
99
+ }
100
+ function schemaIssues(err) {
101
+ if (!isPlainObject(err) && !(err instanceof Error))
102
+ return undefined;
103
+ const issues = err.issues;
104
+ if (!Array.isArray(issues) || issues.length === 0)
105
+ return undefined;
106
+ if (!issues.every((i) => isPlainObject(i) && typeof i.message === 'string'))
107
+ return undefined;
108
+ return issues;
109
+ }
110
+ function issuePath(issue) {
111
+ const parts = (issue.path ?? []).map((p) => String(typeof p === 'object' && p !== null ? p.key : p));
112
+ return parts.join('.');
113
+ }
114
+ /** "Invalid arguments: a.b: msg; c: msg" for a thrown zod / Standard Schema error. */
115
+ function formatIssues(issues) {
116
+ return `Invalid arguments: ${issues
117
+ .map((i) => {
118
+ const p = issuePath(i);
119
+ return p ? `${p}: ${i.message}` : i.message;
120
+ })
121
+ .join('; ')}`;
122
+ }
123
+ const MAX_ERROR_MESSAGE = 2000;
124
+ /** The default `mapError`: the error message only (secret parameters redacted, bounded), never a stack. */
125
+ export function defaultMapError(err) {
126
+ let message;
127
+ if (err instanceof Error)
128
+ message = err.message || err.name;
129
+ else if (typeof err === 'string')
130
+ message = err;
131
+ else
132
+ message = 'Internal error';
133
+ message = maskClientText(message).replace(/[\r\n]+/g, ' ');
134
+ if (message.length > MAX_ERROR_MESSAGE)
135
+ message = `${message.slice(0, MAX_ERROR_MESSAGE)}...`;
136
+ return { message: message || 'Internal error' };
137
+ }
138
+ function isCallToolResult(value) {
139
+ return isPlainObject(value) && Array.isArray(value.content);
140
+ }
141
+ function isLegacyEnvelope(value) {
142
+ return isPlainObject(value) && typeof value.success === 'boolean';
143
+ }
144
+ /**
145
+ * Map a handler's return value onto a CallToolResult. An SDK input-required result
146
+ * (`resultType: 'input_required'`) is returned untouched: the SDK owns it (it skips output validation
147
+ * for it and drives the multi-round-trip flow, or the 2025 legacy shim).
148
+ */
149
+ export function normalizeOutcome(outcome, hasOutputSchema = false) {
150
+ if (isInputRequiredResult(outcome))
151
+ return outcome;
152
+ if (isCallToolResult(outcome))
153
+ return outcome;
154
+ if (isLegacyEnvelope(outcome)) {
155
+ const text = JSON.stringify(outcome, null, 2);
156
+ if (!outcome.success)
157
+ return { content: [{ type: 'text', text }], isError: true };
158
+ const result = { content: [{ type: 'text', text }] };
159
+ if (hasOutputSchema && isPlainObject(outcome.data))
160
+ result.structuredContent = outcome.data;
161
+ return result;
162
+ }
163
+ return toolResult(outcome);
164
+ }
165
+ /** The uniform degraded-mode message. */
166
+ export function notConfiguredMessage(serverName, missing) {
167
+ return `${serverName} is not configured: set ${missing.join(', ')}`;
168
+ }
169
+ /**
170
+ * The client's declared capabilities for this request, read the way the SDK's own input-required gate
171
+ * reads them: the request's `_meta` envelope on 2026-07-28 requests, the `initialize`-scoped value on a
172
+ * 2025-era connection (`getClientCapabilities()`, deprecated in favour of the envelope but functional).
173
+ */
174
+ function clientCapabilitiesOf(server, sdk) {
175
+ if (!sdk)
176
+ return undefined;
177
+ const envelope = sdk.mcpReq.envelope;
178
+ const fromEnvelope = envelope?.[CLIENT_CAPABILITIES_META_KEY];
179
+ return fromEnvelope ?? server.server.getClientCapabilities();
180
+ }
181
+ function contextFor(server, tool, args, sdk, credentials) {
182
+ const cursor = isPlainObject(args) && typeof args.cursor === 'string' && args.cursor !== '' ? args.cursor : undefined;
183
+ const progressToken = sdk?.mcpReq._meta?.progressToken;
184
+ const clientCapabilities = clientCapabilitiesOf(server, sdk);
185
+ const signal = sdk?.mcpReq.signal ?? new AbortController().signal;
186
+ const codec = requestStateCodecOf(server);
187
+ return {
188
+ requestState: () => (codec && sdk ? sdk.mcpReq.requestState() : undefined),
189
+ continueWith: async (state, inputRequests) => {
190
+ if (!codec) {
191
+ throw new RequestStateKeyError('requestState is not configured on this server: set MCP_REQUEST_STATE_KEY and pass requestStateCodec to createMcpServer');
192
+ }
193
+ if (!sdk)
194
+ throw new Error('continueWith needs the SDK request context');
195
+ const requestState = await codec.mint(state, sdk);
196
+ return inputRequired({ ...(inputRequests !== undefined ? { inputRequests } : {}), requestState });
197
+ },
198
+ tool,
199
+ signal,
200
+ authInfo: sdk?.http?.authInfo,
201
+ cursor,
202
+ ...(sdk ? { era: requestEra(sdk) } : {}),
203
+ ...(clientCapabilities !== undefined ? { clientCapabilities } : {}),
204
+ logger: getLogger(),
205
+ credentials,
206
+ sdk,
207
+ ...createClientInput(sdk, clientCapabilities),
208
+ progress: async (progress, total, message) => {
209
+ if (!sdk || progressToken === undefined || signal.aborted)
210
+ return;
211
+ try {
212
+ await sdk.mcpReq.notify({
213
+ method: 'notifications/progress',
214
+ params: {
215
+ progressToken,
216
+ progress,
217
+ ...(total !== undefined ? { total } : {}),
218
+ ...(message !== undefined ? { message } : {}),
219
+ },
220
+ });
221
+ }
222
+ catch {
223
+ // A lost progress notification never fails the tool.
224
+ }
225
+ },
226
+ };
227
+ }
228
+ /** The SDK rethrows exactly this protocol error from its tools/call handler; so must the wrapper. */
229
+ function isRethrownProtocolError(err) {
230
+ return ProtocolError.isInstance(err) && err.code === ProtocolErrorCode.UrlElicitationRequired;
231
+ }
232
+ /**
233
+ * Register `tools` on `server` with `McpServer.registerTool`. Returns the SDK handles by registered
234
+ * name (for `disable()` / `enable()` / `remove()`).
235
+ */
236
+ export function registerTools(server, tools, opts = {}) {
237
+ const handles = new Map();
238
+ const enabled = opts.enabled ? new Set(opts.enabled) : undefined;
239
+ const mapError = opts.mapError ?? defaultMapError;
240
+ const serverName = opts.serverName ?? 'this server';
241
+ const prefix = opts.prefix ?? '';
242
+ const serverLimits = opts.limits ?? {};
243
+ const registry = opts.credentials ?? processCredentials();
244
+ const valueFor = (key) => opts.env?.get(key);
245
+ for (const tool of tools) {
246
+ if (enabled && !enabled.has(tool.name))
247
+ continue;
248
+ const name = `${prefix}${tool.name}`;
249
+ const requires = tool.requires ?? [];
250
+ if (requires.length > 0 && !opts.env) {
251
+ throw new Error(`registerTools: tool ${name} declares requires but no env was passed`);
252
+ }
253
+ const declared = new Set(opts.env?.schema.map((s) => s.key));
254
+ const undeclared = requires.filter((k) => !declared.has(k));
255
+ if (undeclared.length > 0) {
256
+ throw new Error(`registerTools: tool ${name} requires ${undeclared.join(', ')}, which the env schema does not declare`);
257
+ }
258
+ if (tool.paginated && !declaresPageArgs(tool.inputSchema)) {
259
+ throw new Error(`registerTools: paginated tool ${name} must declare cursor and limit in its input schema`);
260
+ }
261
+ const limits = resolveLimits({
262
+ ...(serverLimits.maxItems !== undefined ? { maxResultItems: serverLimits.maxItems } : {}),
263
+ ...(serverLimits.maxBytes !== undefined ? { maxResultBytes: serverLimits.maxBytes } : {}),
264
+ ...(tool.limits?.maxItems !== undefined ? { maxResultItems: tool.limits.maxItems } : {}),
265
+ ...(tool.limits?.maxBytes !== undefined ? { maxResultBytes: tool.limits.maxBytes } : {}),
266
+ }, opts.env ? limitsEnv(opts.env) : process.env);
267
+ const outputSchema = tool.outputSchema !== undefined ? withCredentialsField(tool.outputSchema) : undefined;
268
+ const reportStructured = outputSchema !== undefined && outputSchema !== tool.outputSchema;
269
+ const execute = async (args, sdk, credentials) => {
270
+ const started = Date.now();
271
+ logToolCall(name, args);
272
+ let result;
273
+ let decoded;
274
+ try {
275
+ const missing = requires.filter((k) => !opts.env?.has(k));
276
+ const cursor = isPlainObject(args) && typeof args.cursor === 'string' ? args.cursor : undefined;
277
+ if (cursor !== undefined)
278
+ decoded = decodeToolCursor(name, args, cursor, tool.paginated === true);
279
+ if (missing.length > 0) {
280
+ result = toolError(notConfiguredMessage(serverName, missing));
281
+ }
282
+ else {
283
+ const callArgs = handlerArgs(args, decoded, limits.maxResultItems);
284
+ const outcome = await tool.handler(callArgs, contextFor(server, name, callArgs, sdk, credentials));
285
+ result = normalizeOutcome(outcome, tool.outputSchema !== undefined);
286
+ if (!isInputRequiredResult(result))
287
+ result = maskErrorResult(result);
288
+ }
289
+ }
290
+ catch (err) {
291
+ if (err instanceof InvalidCursorError) {
292
+ result = invalidCursorResult(err);
293
+ logToolResult(name, { isError: true, durationMs: Date.now() - started });
294
+ return result;
295
+ }
296
+ if (isRethrownProtocolError(err)) {
297
+ logToolResult(name, { isError: true, durationMs: Date.now() - started });
298
+ throw err;
299
+ }
300
+ const issues = schemaIssues(err);
301
+ if (err instanceof NoUsableCredentialError) {
302
+ result = toolError(`${serverName} cannot serve ${name}: ${err.message}. Replace or renew the key(s), or wait for a degraded one to recover.`);
303
+ }
304
+ else if (err instanceof InvalidPathSegmentError) {
305
+ // Actionable whatever the server's mapError does; the message names the argument, never the value.
306
+ result = toolError(err.message);
307
+ }
308
+ else if (issues) {
309
+ result = toolError(formatIssues(issues));
310
+ }
311
+ else {
312
+ let mapped;
313
+ try {
314
+ mapped = mapError(err);
315
+ }
316
+ catch {
317
+ mapped = { message: 'Internal error' };
318
+ }
319
+ result = toolError(mapped.code ? `${mapped.code}: ${mapped.message}` : mapped.message);
320
+ }
321
+ }
322
+ // The report's own bytes count against the byte cap, so the final result stays under it.
323
+ const report = credentials.touchedAny ? credentials.report() : [];
324
+ if (isInputRequiredResult(result)) {
325
+ result = attachCredentialMeta(result, report, maskClientText);
326
+ }
327
+ else {
328
+ const reportBytes = credentialReportBytes(report, reportStructured);
329
+ result = enforceResultLimits({
330
+ tool: name,
331
+ args,
332
+ decoded,
333
+ maxItems: limits.maxResultItems,
334
+ maxBytes: Math.max(1, limits.maxResultBytes - reportBytes),
335
+ ...(opts.onOversize ? { onOversize: opts.onOversize } : {}),
336
+ ...(sdk?.http?.authInfo ? { authInfo: sdk.http.authInfo } : {}),
337
+ ...(tool.envelope ? { envelope: tool.envelope } : {}),
338
+ }, result);
339
+ result = attachCredentialReport(result, report, { structured: reportStructured, mask: maskClientText });
340
+ }
341
+ logToolResult(name, {
342
+ isError: !isInputRequiredResult(result) && result.isError === true,
343
+ durationMs: Date.now() - started,
344
+ });
345
+ return result;
346
+ };
347
+ // The request scope lets the protocol log forwarder find this request's SDK context.
348
+ const run = (args, sdk) => {
349
+ const credentials = new CredentialScope(registry, valueFor);
350
+ const call = () => runWithCredentialScope(credentials, () => execute(args, sdk, credentials));
351
+ return sdk ? runWithRequestContext(sdk, call) : call();
352
+ };
353
+ const config = {
354
+ ...(tool.title !== undefined ? { title: tool.title } : {}),
355
+ description: tool.description,
356
+ inputSchema: tool.inputSchema,
357
+ ...(outputSchema !== undefined ? { outputSchema } : {}),
358
+ annotations: tool.annotations,
359
+ ...(tool.icons !== undefined ? { icons: tool.icons } : {}),
360
+ ...(tool.scopeChallenge !== undefined ? { scopeChallenge: tool.scopeChallenge } : {}),
361
+ ...(tool._meta !== undefined ? { _meta: tool._meta } : {}),
362
+ };
363
+ const handle = server.registerTool(name, config, (args, ctx) => run(args, ctx));
364
+ if (opts.surface)
365
+ bindToSurface(server, opts.surface, 'tool', name, handle);
366
+ handles.set(name, handle);
367
+ }
368
+ return handles;
369
+ }
370
+ //# sourceMappingURL=tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tools.js","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"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"}
@@ -1,102 +1,193 @@
1
1
  /**
2
- * @novorb/mcp-core — Transport
2
+ * @novorb/mcp-core - Transport
3
3
  *
4
- * Unified transport for MCP servers. Selects between stdio and native Streamable HTTP
5
- * based on the MCP_TRANSPORT environment variable.
4
+ * Unified transport for MCP servers on SDK v2. Selects between stdio and Streamable HTTP from the
5
+ * MCP_TRANSPORT environment variable; both legs take the SAME server factory.
6
6
  *
7
- * HTTP mode is stateless (sessionIdGenerator: undefined) — compatible with MCPize Cloud Run,
8
- * Apify Standby, and any other scale-to-zero host. One transport instance is created per
9
- * request; the server instance is resolved once and reconnected per request (SDK 1.29+).
7
+ * - stdio: `serveStdio(factory)` from `@modelcontextprotocol/server/stdio` (one instance per
8
+ * connection; the client's opening message picks the protocol era).
9
+ * - http: `createMcpHandler(factory, { legacy: 'stateless' })` (the SDK default `responseMode: 'auto'`:
10
+ * one JSON body unless the handler emits progress or log notifications first, then SSE) adapted with
11
+ * `toNodeHandler` from `@modelcontextprotocol/node`, behind mcp-core's own `node:http` server that
12
+ * adds `/health`, the fail-closed Bearer gate (the SDK's `verifyBearerToken` over the static key or a
13
+ * pluggable verifier, `req.auth` set for the SDK), Host/Origin allow-lists and the 415/413 guards.
14
+ * Stateless: a fresh instance per request, 2025-era clients served by the SDK's stateless fallback.
10
15
  *
11
16
  * Usage:
12
17
  * import { startMcpServer } from '@novorb/mcp-core/transport';
18
+ * await startMcpServer(() => buildServer());
13
19
  *
14
- * // Factory (recommended for HTTP — ensures clean state per request):
15
- * await startMcpServer(() => createServer(services));
16
- *
17
- * // Server instance (fine for stdio; also works for HTTP in SDK 1.29+):
18
- * await startMcpServer(server);
19
- *
20
- * Environment variables:
21
- * MCP_TRANSPORT — 'stdio' (default) | 'http'
22
- * PORT — listen port for HTTP transport (default: 8080)
23
- * MCP_HTTP_HOST — bind address for HTTP (default: '0.0.0.0' for container hosts; set
24
- * '127.0.0.1' for local-only)
25
- * MCP_API_KEY — Bearer token for HTTP auth. REQUIRED in HTTP mode unless MCP_AUTH_DISABLED.
26
- * MCP_AUTH_DISABLED — set 'true' to run HTTP WITHOUT auth (only when a gateway/platform fronts it)
27
- * MCP_MAX_BODY_BYTES — max accepted POST body size (default: 4 MiB)
28
- * MCP_ALLOWED_HOSTS — comma-separated Host allowlist; setting it enables DNS-rebinding protection
29
- * MCP_ALLOWED_ORIGINS — comma-separated Origin allowlist (also enables DNS-rebinding protection)
20
+ * Environment variables (an explicit option wins):
21
+ * MCP_TRANSPORT - 'stdio' (default) | 'http'; any other value throws
22
+ * PORT - listen port for HTTP transport (default: 8080)
23
+ * MCP_HTTP_HOST - bind address for HTTP (default: '0.0.0.0'; set '127.0.0.1' for local-only)
24
+ * MCP_API_KEY - Bearer token for HTTP auth. REQUIRED in HTTP mode unless MCP_AUTH_DISABLED or
25
+ * a `verifier` is passed.
26
+ * MCP_AUTH_DISABLED - set 'true' to run HTTP WITHOUT auth (only when a gateway/platform fronts it)
27
+ * MCP_MAX_BODY_BYTES - max accepted POST body size (default: 4 MiB)
28
+ * MCP_ALLOWED_HOSTS - comma-separated Host allowlist; setting it enables DNS-rebinding protection
29
+ * MCP_ALLOWED_ORIGINS - comma-separated Origin allowlist (also enables DNS-rebinding protection)
30
30
  */
31
- import { IncomingMessage, ServerResponse } from 'node:http';
32
- /** Accepts both the high-level McpServer and the low-level Server */
33
- type AnyMcpServer = {
34
- connect(transport: unknown): Promise<void>;
35
- close?(): Promise<void>;
36
- };
37
- /** A server instance or a factory that creates one per request */
38
- type ServerOrFactory = AnyMcpServer | (() => AnyMcpServer);
31
+ import { type IncomingMessage, type ServerResponse } from 'node:http';
32
+ import { type AuthInfo, type McpRequestContext, type McpServer, type Server, type ServerEventBus, type ServerNotifier, type VerifyBearerTokenOptions } from '@modelcontextprotocol/server';
33
+ import { type HttpAuthOptions } from './auth.js';
34
+ /**
35
+ * What the SDK hands a factory per serving unit: the protocol `era` ('modern' | 'legacy'), and on HTTP
36
+ * the verified `authInfo` (set by the Bearer gate) and the original `requestInfo`.
37
+ */
38
+ export type RequestContext = McpRequestContext;
39
+ /**
40
+ * Builds a fresh server instance: once per connection on stdio, once per request on HTTP. Receives the
41
+ * SDK's per-request context; zero-argument factories remain valid.
42
+ */
43
+ export type ServerFactory = (ctx: RequestContext) => McpServer | Server;
44
+ /** A started transport: resolved once stdio is serving or the HTTP listener is bound. */
45
+ export interface TransportHandle {
46
+ mode: TransportMode;
47
+ /** http only: the bound host. */
48
+ host?: string;
49
+ /** http only: the bound port (the real one when 0 was requested). */
50
+ port?: number;
51
+ /** http only: the `/mcp` endpoint URL. */
52
+ url?: string;
53
+ /**
54
+ * Resolves once the transport has ended for any reason: `close()`, or (stdio) the client closing its
55
+ * end of the pipe (stdin end / close). `runMcpServer` uses it to dispose and exit on a stdio EOF.
56
+ */
57
+ closed: Promise<void>;
58
+ /** The change-event bus this transport delivers from (`TransportOptions.bus`, else the process bus). */
59
+ bus: ServerEventBus;
60
+ /** Publish list-changed / resource-updated events to every connection of this transport. */
61
+ notify: ServerNotifier;
62
+ /** Close the transport (SDK handler, then the listener / stdio connection). Idempotent. */
63
+ close(): Promise<void>;
64
+ }
65
+ /** A server instance (stdio only) or a factory (stdio and HTTP). */
66
+ export type ServerOrFactory = McpServer | Server | ServerFactory;
39
67
  export type TransportMode = 'stdio' | 'http';
40
68
  export interface TransportOptions {
41
69
  /** Transport mode. Defaults to MCP_TRANSPORT env var, falling back to 'stdio'. */
42
70
  mode?: TransportMode;
43
71
  /** HTTP listen port. Defaults to PORT env var, falling back to 8080. */
44
72
  port?: number;
73
+ /** HTTP bind address. Defaults to MCP_HTTP_HOST, falling back to 0.0.0.0. */
74
+ host?: string;
45
75
  /**
46
76
  * Optional Bearer token for HTTP auth. When set, all /mcp requests must include
47
77
  * `Authorization: Bearer <apiKey>`. Defaults to MCP_API_KEY env var.
48
78
  * Set to null to EXPLICITLY disable auth (equivalent to MCP_AUTH_DISABLED=true).
49
79
  */
50
80
  apiKey?: string | null;
81
+ /**
82
+ * Bearer gate options: a pluggable `verifier` (replaces the static key, for example a JWT verifier),
83
+ * `requiredScopes`, `resourceMetadataUrl`, `expectedResource`, and the API key's `AuthInfo` fields.
84
+ */
85
+ auth?: HttpAuthOptions;
86
+ /** POST body cap in bytes. Defaults to MCP_MAX_BODY_BYTES, falling back to 4 MiB. */
87
+ maxBodyBytes?: number;
88
+ /** Host allow-list. Defaults to MCP_ALLOWED_HOSTS. */
89
+ allowedHosts?: string[];
90
+ /** Origin allow-list. Defaults to MCP_ALLOWED_ORIGINS. */
91
+ allowedOrigins?: string[];
92
+ /**
93
+ * Install SIGINT/SIGTERM handlers that close the transport (default true). `runMcpServer` passes
94
+ * false and owns the signals itself (close transport, dispose, exit).
95
+ */
96
+ handleSignals?: boolean;
97
+ /**
98
+ * The change-event bus (default: the process bus, `processBus()`). HTTP: the SDK serves
99
+ * `subscriptions/listen` streams from it; stdio: every connection's instance forwards its events.
100
+ */
101
+ bus?: ServerEventBus;
51
102
  }
103
+ /** Default POST body cap (the SDK's own default too). */
104
+ export declare const DEFAULT_MAX_BODY_BYTES: number;
52
105
  /**
53
106
  * Constant-time comparison of the Authorization header against `Bearer <apiKey>`.
54
107
  * Both sides are SHA-256-hashed first so `timingSafeEqual` never throws on a length mismatch and the
55
- * token length is not itself a timing oracle.
108
+ * token length is not itself a timing oracle. (The transport itself now verifies through the SDK's
109
+ * `verifyBearerToken` with `apiKeyVerifier`, which compares the same way.)
56
110
  */
57
111
  export declare function bearerMatches(authHeader: string, apiKey: string): boolean;
58
112
  export interface HttpAuthResolution {
59
113
  /** Whether the Bearer check is enforced on /mcp requests. */
60
114
  authEnabled: boolean;
61
- /** The resolved key ('' when auth is explicitly disabled). */
115
+ /** The resolved key ('' when auth is explicitly disabled or a verifier replaces it). */
62
116
  apiKey: string;
63
117
  }
64
118
  /**
65
- * Resolve HTTP auth — FAIL CLOSED. `apiKey: null` (programmatic) or MCP_AUTH_DISABLED=true are the
119
+ * Resolve HTTP auth - FAIL CLOSED. `apiKey: null` (programmatic) or MCP_AUTH_DISABLED=true are the
66
120
  * only ways to run open; a missing/empty MCP_API_KEY is treated as "not configured" (not a valid
67
- * empty key) and THROWS, so a config typo can't silently downgrade the endpoint to no-auth.
121
+ * empty key) and THROWS, so a config typo can't silently downgrade the endpoint to no-auth. A passed
122
+ * `auth.verifier` always enforces auth (it wins over every "disabled" switch).
68
123
  */
69
- export declare function resolveHttpAuth(options: Pick<TransportOptions, 'apiKey'>, env?: NodeJS.ProcessEnv): HttpAuthResolution;
70
- /** Resolved configuration for the HTTP request handler — everything `startHttp` derives once at boot. */
124
+ export declare function resolveHttpAuth(options: Pick<TransportOptions, 'apiKey' | 'auth'>, env?: NodeJS.ProcessEnv): HttpAuthResolution;
125
+ /** Resolved configuration for the HTTP request handler: everything `startHttp` derives once at boot. */
71
126
  export interface RequestHandlerConfig {
72
- /** Returns a server instance to connect for a request (fresh per request in the stateless model). */
73
- getServer: () => AnyMcpServer;
74
- /** Whether the Bearer check is enforced on /mcp requests. */
127
+ /** Builds a fresh server instance for each request (one instance serves one connection in SDK v2). */
128
+ getServer: ServerFactory;
129
+ /** Whether the Bearer check is enforced on /mcp requests (with the API key, or `auth.verifier`). */
75
130
  authEnabled: boolean;
76
- /** The resolved Bearer key ('' when auth is disabled). */
131
+ /** The resolved Bearer key ('' when auth is disabled or a verifier replaces it). */
77
132
  apiKey: string;
78
- /** Max accepted POST body size in bytes (→ 413 when exceeded). */
133
+ /** Bearer gate options (verifier, scopes, resource metadata, the API key's AuthInfo fields). */
134
+ auth?: HttpAuthOptions;
135
+ /** Max accepted POST body size in bytes (413 when exceeded). */
79
136
  maxBodyBytes: number;
80
- /** Whether to enable the SDK's DNS-rebinding (Host/Origin) protection. */
137
+ /** Whether to enforce the Host/Origin allow-lists (DNS-rebinding protection). */
81
138
  enableDnsRebindingProtection: boolean;
82
- /** Host allowlist (only consulted when DNS-rebinding protection is enabled). */
139
+ /** Host allowlist; `host` or `host:port` entries, matched port-agnostically by hostname. */
83
140
  allowedHosts: string[];
84
- /** Origin allowlist (only consulted when DNS-rebinding protection is enabled). */
141
+ /** Origin allowlist; full origins or bare hostnames (matched by hostname), or `<scheme>://*`. */
85
142
  allowedOrigins: string[];
143
+ /** The change-event bus `subscriptions/listen` streams subscribe to (default the process bus). */
144
+ bus?: ServerEventBus;
86
145
  }
146
+ /** The `(req, res)` listener for `node:http`, plus `close()` to tear down the SDK handler. */
147
+ export type McpRequestHandler = ((req: IncomingMessage, res: ServerResponse) => Promise<void>) & {
148
+ close(): Promise<void>;
149
+ };
150
+ /** `host` or `host:port` -> the bare hostname the SDK's port-agnostic Host validation compares. */
151
+ export declare function toHostname(entry: string): string;
152
+ /**
153
+ * A full origin (`https://app.example.com:443`) -> its hostname; bare hostnames and `<scheme>://*`
154
+ * entries pass unchanged. The SDK honours a lowercase `<scheme>://*` entry (for example
155
+ * `chrome-extension://*`) as "every origin of that scheme", but never `http://*` or `https://*`.
156
+ */
157
+ export declare function toOriginHostname(entry: string): string;
158
+ /** Split a comma-separated allow-list env value. */
159
+ export declare function parseList(value: string | undefined): string[];
160
+ /** `IncomingMessage` with the `auth` the SDK node adapter forwards as `authInfo`. */
161
+ export type AuthenticatedRequest = IncomingMessage & {
162
+ auth?: AuthInfo;
163
+ };
164
+ /**
165
+ * Run the Bearer gate: answers the SDK challenge (401/403 with `WWW-Authenticate`) and returns false,
166
+ * or sets `req.auth` and returns true. With no gate configured it lets the request through.
167
+ */
168
+ export declare function runBearerGate(req: AuthenticatedRequest, res: ServerResponse, gate: VerifyBearerTokenOptions | undefined): Promise<boolean>;
169
+ /** The content-type check: the SDK's media-type essence comparison (`application/json`, params allowed). */
170
+ export declare function isJsonRequest(req: IncomingMessage): boolean;
87
171
  /**
88
172
  * Build the `(req, res)` handler for the HTTP transport. Extracted from `startHttp` so the routing,
89
- * auth, content-type/size guards, and error handling are unit-testable with mock req/res — no socket
90
- * binding required.
173
+ * auth, content-type/size guards, and error handling are unit-testable with mock req/res, no socket
174
+ * binding required. Order: `/health`, Bearer check, path check, Host/Origin allow-lists, 415, 413,
175
+ * then the SDK handler.
91
176
  */
92
- export declare function createRequestHandler(cfg: RequestHandlerConfig): (req: IncomingMessage, res: ServerResponse) => Promise<void>;
177
+ export declare function createRequestHandler(cfg: RequestHandlerConfig): McpRequestHandler;
178
+ /** The transport mode from the option, else MCP_TRANSPORT, else stdio; anything else throws. */
179
+ export declare function resolveTransportMode(option: TransportMode | undefined, env?: NodeJS.ProcessEnv): "stdio" | "http";
93
180
  /**
94
- * Start an MCP server with the configured transport.
181
+ * Start an MCP server with the configured transport. Resolves with a `TransportHandle` once serving:
95
182
  *
96
- * For stdio: connects once and keeps the process alive.
97
- * For http: starts a stateless HTTP server. GET /health is always available.
98
- * Pass a factory function to get a fresh server instance per request.
183
+ * For stdio: serves the process' stdin/stdout. An instance is accepted and wrapped as `() => instance`.
184
+ * With `handleSignals` (default) SIGINT/SIGTERM close the connection and re-raise the signal
185
+ * when no other listener remains. `closed` resolves when the client closes stdin.
186
+ * For http: starts a stateless HTTP server and resolves once the listener is bound (the process stays
187
+ * alive on the listener). With `handleSignals` (default) SIGINT/SIGTERM close it. Requires a
188
+ * factory (a fresh instance per request).
99
189
  */
100
- export declare function startMcpServer(serverOrFactory: ServerOrFactory, options?: TransportOptions): Promise<void>;
101
- export {};
190
+ export declare function startMcpServer(serverOrFactory: ServerOrFactory, options?: TransportOptions): Promise<TransportHandle>;
191
+ /** A factory whose instances forward the bus's change events (a stdio connection is long-lived). */
192
+ export declare function notifyingFactory(factory: ServerFactory, bus: ServerEventBus): ServerFactory;
102
193
  //# sourceMappingURL=transport.d.ts.map