mcp-remote 0.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.
package/.prettierrc ADDED
@@ -0,0 +1,14 @@
1
+ {
2
+ "printWidth": 140,
3
+ "singleQuote": true,
4
+ "semi": false,
5
+ "useTabs": false,
6
+ "overrides": [
7
+ {
8
+ "files": ["*.jsonc"],
9
+ "options": {
10
+ "trailingComma": "none"
11
+ }
12
+ }
13
+ ]
14
+ }
package/package.json ADDED
@@ -0,0 +1,14 @@
1
+ {
2
+ "name": "mcp-remote",
3
+ "version": "0.0.1",
4
+ "type": "module",
5
+ "devDependencies": {
6
+ "@modelcontextprotocol/sdk": "^1.7.0",
7
+ "@types/express": "^5.0.0",
8
+ "@types/node": "^22.13.10",
9
+ "express": "^4.21.2",
10
+ "open": "^10.1.0",
11
+ "prettier": "^3.5.3",
12
+ "tsx": "^4.19.3"
13
+ }
14
+ }
@@ -0,0 +1,307 @@
1
+ #!/usr/bin/env node
2
+
3
+ // sse-auth-client.ts - MCP Client with OAuth support
4
+ // Run with: npx tsx sse-auth-client.ts sse-auth-client.ts https://example.remote/server [callback-port]
5
+
6
+ import express from 'express'
7
+ import open from 'open'
8
+ import fs from 'fs/promises'
9
+ import path from 'path'
10
+ import os from 'os'
11
+ import crypto from 'crypto'
12
+ import { EventEmitter } from 'events'
13
+ import { Client } from '@modelcontextprotocol/sdk/client/index.js'
14
+ import { SSEClientTransport } from '@modelcontextprotocol/sdk/client/sse.js'
15
+ import { OAuthClientProvider, auth, UnauthorizedError } from '@modelcontextprotocol/sdk/client/auth.js'
16
+ import { ListResourcesResultSchema, ListToolsResultSchema } from '@modelcontextprotocol/sdk/types.js'
17
+ import {
18
+ OAuthClientInformation,
19
+ OAuthClientInformationFull,
20
+ OAuthClientInformationSchema,
21
+ OAuthTokens,
22
+ OAuthTokensSchema,
23
+ } from '@modelcontextprotocol/sdk/shared/auth.js'
24
+
25
+ // Implement OAuth client provider for Node.js environment
26
+ class NodeOAuthClientProvider implements OAuthClientProvider {
27
+ private configDir: string
28
+ private serverUrlHash: string
29
+
30
+ constructor(
31
+ private serverUrl: string,
32
+ private callbackPort: number = 3333,
33
+ private callbackPath: string = '/oauth/callback',
34
+ ) {
35
+ this.serverUrlHash = crypto.createHash('md5').update(serverUrl).digest('hex')
36
+ this.configDir = path.join(os.homedir(), '.mcp-auth')
37
+ }
38
+
39
+ get redirectUrl(): string {
40
+ return `http://localhost:${this.callbackPort}${this.callbackPath}`
41
+ }
42
+
43
+ get clientMetadata() {
44
+ return {
45
+ redirect_uris: [this.redirectUrl],
46
+ token_endpoint_auth_method: 'none',
47
+ grant_types: ['authorization_code', 'refresh_token'],
48
+ response_types: ['code'],
49
+ client_name: 'MCP CLI Client',
50
+ client_uri: 'https://github.com/modelcontextprotocol/mcp-cli',
51
+ }
52
+ }
53
+
54
+ private async ensureConfigDir() {
55
+ try {
56
+ await fs.mkdir(this.configDir, { recursive: true })
57
+ } catch (error) {
58
+ console.error('Error creating config directory:', error)
59
+ throw error
60
+ }
61
+ }
62
+
63
+ private async readFile<T>(filename: string, schema: any): Promise<T | undefined> {
64
+ try {
65
+ await this.ensureConfigDir()
66
+ const filePath = path.join(this.configDir, `${this.serverUrlHash}_${filename}`)
67
+ const content = await fs.readFile(filePath, 'utf-8')
68
+ return await schema.parseAsync(JSON.parse(content))
69
+ } catch (error) {
70
+ if ((error as NodeJS.ErrnoException).code === 'ENOENT') {
71
+ return undefined
72
+ }
73
+ return undefined
74
+ }
75
+ }
76
+
77
+ private async writeFile(filename: string, data: any) {
78
+ try {
79
+ await this.ensureConfigDir()
80
+ const filePath = path.join(this.configDir, `${this.serverUrlHash}_${filename}`)
81
+ await fs.writeFile(filePath, JSON.stringify(data, null, 2), 'utf-8')
82
+ } catch (error) {
83
+ console.error(`Error writing ${filename}:`, error)
84
+ throw error
85
+ }
86
+ }
87
+
88
+ private async writeTextFile(filename: string, text: string) {
89
+ try {
90
+ await this.ensureConfigDir()
91
+ const filePath = path.join(this.configDir, `${this.serverUrlHash}_${filename}`)
92
+ await fs.writeFile(filePath, text, 'utf-8')
93
+ } catch (error) {
94
+ console.error(`Error writing ${filename}:`, error)
95
+ throw error
96
+ }
97
+ }
98
+
99
+ private async readTextFile(filename: string): Promise<string> {
100
+ try {
101
+ await this.ensureConfigDir()
102
+ const filePath = path.join(this.configDir, `${this.serverUrlHash}_${filename}`)
103
+ return await fs.readFile(filePath, 'utf-8')
104
+ } catch (error) {
105
+ throw new Error('No code verifier saved for session')
106
+ }
107
+ }
108
+
109
+ async clientInformation(): Promise<OAuthClientInformation | undefined> {
110
+ return this.readFile<OAuthClientInformation>('client_info.json', OAuthClientInformationSchema)
111
+ }
112
+
113
+ async saveClientInformation(clientInformation: OAuthClientInformationFull): Promise<void> {
114
+ await this.writeFile('client_info.json', clientInformation)
115
+ }
116
+
117
+ async tokens(): Promise<OAuthTokens | undefined> {
118
+ return this.readFile<OAuthTokens>('tokens.json', OAuthTokensSchema)
119
+ }
120
+
121
+ async saveTokens(tokens: OAuthTokens): Promise<void> {
122
+ await this.writeFile('tokens.json', tokens)
123
+ }
124
+
125
+ async redirectToAuthorization(authorizationUrl: URL): Promise<void> {
126
+ console.log(`\nPlease authorize this client by visiting:\n${authorizationUrl.toString()}\n`)
127
+ try {
128
+ await open(authorizationUrl.toString())
129
+ console.log('Browser opened automatically.')
130
+ } catch (error) {
131
+ console.log('Could not open browser automatically. Please copy and paste the URL above into your browser.')
132
+ }
133
+ }
134
+
135
+ async saveCodeVerifier(codeVerifier: string): Promise<void> {
136
+ await this.writeTextFile('code_verifier.txt', codeVerifier)
137
+ }
138
+
139
+ async codeVerifier(): Promise<string> {
140
+ return await this.readTextFile('code_verifier.txt')
141
+ }
142
+ }
143
+
144
+ // Main function to run the client
145
+ async function runClient(serverUrl: string, callbackPort: number) {
146
+ // Set up event emitter for auth flow
147
+ const events = new EventEmitter()
148
+
149
+ // Create the OAuth client provider
150
+ const authProvider = new NodeOAuthClientProvider(serverUrl, callbackPort)
151
+
152
+ // Create the client
153
+ const client = new Client(
154
+ {
155
+ name: 'mcp-cli',
156
+ version: '0.1.0',
157
+ },
158
+ {
159
+ capabilities: {
160
+ sampling: {},
161
+ },
162
+ },
163
+ )
164
+
165
+ // Create the transport
166
+ const url = new URL(serverUrl)
167
+
168
+ function initTransport() {
169
+ const transport = new SSEClientTransport(url, { authProvider })
170
+
171
+ // Set up message and error handlers
172
+ transport.onmessage = (message) => {
173
+ console.log('Received message:', JSON.stringify(message, null, 2))
174
+ }
175
+
176
+ transport.onerror = (error) => {
177
+ console.error('Transport error:', error)
178
+ }
179
+
180
+ transport.onclose = () => {
181
+ console.log('Connection closed.')
182
+ process.exit(0)
183
+ }
184
+ return transport
185
+ }
186
+
187
+ const transport = initTransport()
188
+
189
+ // Set up an HTTP server to handle OAuth callback
190
+ let authCode: string | null = null
191
+ const app = express()
192
+
193
+ app.get('/oauth/callback', (req, res) => {
194
+ const code = req.query.code as string | undefined
195
+ if (!code) {
196
+ res.status(400).send('Error: No authorization code received')
197
+ return
198
+ }
199
+
200
+ authCode = code
201
+ res.send('Authorization successful! You may close this window and return to the CLI.')
202
+
203
+ // Notify main flow that auth code is available
204
+ events.emit('auth-code-received', code)
205
+ })
206
+
207
+ const server = app.listen(callbackPort, () => {
208
+ console.log(`OAuth callback server running at http://localhost:${callbackPort}`)
209
+ })
210
+
211
+ // Function to wait for auth code
212
+ const waitForAuthCode = (): Promise<string> => {
213
+ return new Promise((resolve) => {
214
+ if (authCode) {
215
+ resolve(authCode)
216
+ return
217
+ }
218
+
219
+ events.once('auth-code-received', (code) => {
220
+ resolve(code)
221
+ })
222
+ })
223
+ }
224
+
225
+ // Try to connect
226
+ try {
227
+ console.log('Connecting to server...')
228
+ await client.connect(transport)
229
+ console.log('Connected successfully!')
230
+
231
+ // Send a resources/list request
232
+ // console.log("Requesting resource list...");
233
+ // const result = await client.request({ method: "resources/list" }, ListResourcesResultSchema);
234
+ // console.log("Resources:", JSON.stringify(result, null, 2));
235
+
236
+ console.log('Request tools list...')
237
+ const tools = await client.request({ method: 'tools/list' }, ListToolsResultSchema)
238
+ console.log('Tools:', JSON.stringify(tools, null, 2))
239
+
240
+ console.log('Listening for messages. Press Ctrl+C to exit.')
241
+ } catch (error) {
242
+ if (error instanceof UnauthorizedError || (error instanceof Error && error.message.includes('Unauthorized'))) {
243
+ console.log('Authentication required. Waiting for authorization...')
244
+
245
+ // Wait for the authorization code from the callback
246
+ const code = await waitForAuthCode()
247
+
248
+ try {
249
+ console.log('Completing authorization...')
250
+ await transport.finishAuth(code)
251
+
252
+ // Start a new transport here? Ok cause it's going to write to the file maybe?
253
+
254
+ // Reconnect after authorization
255
+ console.log('Connecting after authorization...')
256
+ await client.connect(initTransport())
257
+
258
+ console.log('Connected successfully!')
259
+
260
+ // // Send a resources/list request
261
+ // console.log("Requesting resource list...");
262
+ // const result = await client.request({ method: "resources/list" }, ListResourcesResultSchema);
263
+ // console.log("Resources:", JSON.stringify(result, null, 2));2));
264
+
265
+ console.log('Request tools list...')
266
+ const tools = await client.request({ method: 'tools/list' }, ListToolsResultSchema)
267
+ console.log('Tools:', JSON.stringify(tools, null, 2))
268
+
269
+ console.log('Listening for messages. Press Ctrl+C to exit.')
270
+ } catch (authError) {
271
+ console.error('Authorization error:', authError)
272
+ server.close()
273
+ process.exit(1)
274
+ }
275
+ } else {
276
+ console.error('Connection error:', error)
277
+ server.close()
278
+ process.exit(1)
279
+ }
280
+ }
281
+
282
+ // Handle shutdown
283
+ process.on('SIGINT', async () => {
284
+ console.log('\nClosing connection...')
285
+ await client.close()
286
+ server.close()
287
+ process.exit(0)
288
+ })
289
+
290
+ // Keep the process alive
291
+ process.stdin.resume()
292
+ }
293
+
294
+ // Parse command-line arguments
295
+ const args = process.argv.slice(2)
296
+ const serverUrl = args[0]
297
+ const callbackPort = args[1] ? parseInt(args[1]) : 3333
298
+
299
+ if (!serverUrl || !serverUrl.startsWith('https://')) {
300
+ console.error('Usage: node --experimental-strip-types sse-auth-client.ts <https://server-url> [callback-port]')
301
+ process.exit(1)
302
+ }
303
+
304
+ runClient(serverUrl, callbackPort).catch((error) => {
305
+ console.error('Fatal error:', error)
306
+ process.exit(1)
307
+ })
@@ -0,0 +1,323 @@
1
+ #!/usr/bin/env node
2
+
3
+ // sse-auth-proxy.ts - MCP Proxy with OAuth support
4
+ // Run with: npx tsx sse-auth-proxy.ts https://example.remote/server [callback-port]
5
+
6
+ import express from 'express'
7
+ import open from 'open'
8
+ import fs from 'fs/promises'
9
+ import path from 'path'
10
+ import crypto from 'crypto'
11
+ import { EventEmitter } from 'events'
12
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js'
13
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'
14
+ import { SSEClientTransport } from '@modelcontextprotocol/sdk/client/sse.js'
15
+ import { OAuthClientProvider, auth, UnauthorizedError } from '@modelcontextprotocol/sdk/client/auth.js'
16
+ import {
17
+ OAuthClientInformation,
18
+ OAuthClientInformationFull,
19
+ OAuthClientInformationSchema,
20
+ OAuthTokens,
21
+ OAuthTokensSchema,
22
+ } from '@modelcontextprotocol/sdk/shared/auth.js'
23
+ import { Transport } from '@modelcontextprotocol/sdk/shared/transport.js'
24
+ import os from 'os'
25
+
26
+ // Implement OAuth client provider for Node.js environment
27
+ class NodeOAuthClientProvider implements OAuthClientProvider {
28
+ private configDir: string
29
+ private serverUrlHash: string
30
+
31
+ constructor(
32
+ private serverUrl: string,
33
+ private callbackPort: number = 3334,
34
+ private callbackPath: string = '/oauth/callback',
35
+ ) {
36
+ this.serverUrlHash = crypto.createHash('md5').update(serverUrl).digest('hex')
37
+ this.configDir = path.join(os.homedir(), '.mcp-auth')
38
+ }
39
+
40
+ get redirectUrl(): string {
41
+ return `http://localhost:${this.callbackPort}${this.callbackPath}`
42
+ }
43
+
44
+ get clientMetadata() {
45
+ return {
46
+ redirect_uris: [this.redirectUrl],
47
+ token_endpoint_auth_method: 'none',
48
+ grant_types: ['authorization_code', 'refresh_token'],
49
+ response_types: ['code'],
50
+ client_name: 'MCP CLI Proxy',
51
+ client_uri: 'https://github.com/modelcontextprotocol/mcp-cli',
52
+ }
53
+ }
54
+
55
+ private async ensureConfigDir() {
56
+ try {
57
+ await fs.mkdir(this.configDir, { recursive: true })
58
+ } catch (error) {
59
+ console.error('Error creating config directory:', error)
60
+ throw error
61
+ }
62
+ }
63
+
64
+ private async readFile<T>(filename: string, schema: any): Promise<T | undefined> {
65
+ try {
66
+ await this.ensureConfigDir()
67
+ const filePath = path.join(this.configDir, `${this.serverUrlHash}_${filename}`)
68
+ const content = await fs.readFile(filePath, 'utf-8')
69
+ return await schema.parseAsync(JSON.parse(content))
70
+ } catch (error) {
71
+ if ((error as NodeJS.ErrnoException).code === 'ENOENT') {
72
+ return undefined
73
+ }
74
+ return undefined
75
+ }
76
+ }
77
+
78
+ private async writeFile(filename: string, data: any) {
79
+ try {
80
+ await this.ensureConfigDir()
81
+ const filePath = path.join(this.configDir, `${this.serverUrlHash}_${filename}`)
82
+ await fs.writeFile(filePath, JSON.stringify(data, null, 2), 'utf-8')
83
+ } catch (error) {
84
+ console.error(`Error writing ${filename}:`, error)
85
+ throw error
86
+ }
87
+ }
88
+
89
+ private async writeTextFile(filename: string, text: string) {
90
+ try {
91
+ await this.ensureConfigDir()
92
+ const filePath = path.join(this.configDir, `${this.serverUrlHash}_${filename}`)
93
+ await fs.writeFile(filePath, text, 'utf-8')
94
+ } catch (error) {
95
+ console.error(`Error writing ${filename}:`, error)
96
+ throw error
97
+ }
98
+ }
99
+
100
+ private async readTextFile(filename: string): Promise<string> {
101
+ try {
102
+ await this.ensureConfigDir()
103
+ const filePath = path.join(this.configDir, `${this.serverUrlHash}_${filename}`)
104
+ return await fs.readFile(filePath, 'utf-8')
105
+ } catch (error) {
106
+ throw new Error('No code verifier saved for session')
107
+ }
108
+ }
109
+
110
+ async clientInformation(): Promise<OAuthClientInformation | undefined> {
111
+ return this.readFile<OAuthClientInformation>('client_info.json', OAuthClientInformationSchema)
112
+ }
113
+
114
+ async saveClientInformation(clientInformation: OAuthClientInformationFull): Promise<void> {
115
+ await this.writeFile('client_info.json', clientInformation)
116
+ }
117
+
118
+ async tokens(): Promise<OAuthTokens | undefined> {
119
+ return this.readFile<OAuthTokens>('tokens.json', OAuthTokensSchema)
120
+ }
121
+
122
+ async saveTokens(tokens: OAuthTokens): Promise<void> {
123
+ await this.writeFile('tokens.json', tokens)
124
+ }
125
+
126
+ async redirectToAuthorization(authorizationUrl: URL): Promise<void> {
127
+ console.error(`\nPlease authorize this client by visiting:\n${authorizationUrl.toString()}\n`)
128
+ try {
129
+ await open(authorizationUrl.toString())
130
+ console.error('Browser opened automatically.')
131
+ } catch (error) {
132
+ console.error('Could not open browser automatically. Please copy and paste the URL above into your browser.')
133
+ }
134
+ }
135
+
136
+ async saveCodeVerifier(codeVerifier: string): Promise<void> {
137
+ await this.writeTextFile('code_verifier.txt', codeVerifier)
138
+ }
139
+
140
+ async codeVerifier(): Promise<string> {
141
+ return await this.readTextFile('code_verifier.txt')
142
+ }
143
+ }
144
+
145
+ // Function to proxy messages between two transports
146
+ function mcpProxy({ transportToClient, transportToServer }: { transportToClient: Transport; transportToServer: Transport }) {
147
+ let transportToClientClosed = false
148
+ let transportToServerClosed = false
149
+
150
+ transportToClient.onmessage = (message) => {
151
+ console.error('[Local→Remote]', message.method || message.id)
152
+ transportToServer.send(message).catch(onServerError)
153
+ }
154
+
155
+ transportToServer.onmessage = (message) => {
156
+ console.error('[Remote→Local]', message.method || message.id)
157
+ transportToClient.send(message).catch(onClientError)
158
+ }
159
+
160
+ transportToClient.onclose = () => {
161
+ if (transportToServerClosed) {
162
+ return
163
+ }
164
+
165
+ transportToClientClosed = true
166
+ transportToServer.close().catch(onServerError)
167
+ }
168
+
169
+ transportToServer.onclose = () => {
170
+ if (transportToClientClosed) {
171
+ return
172
+ }
173
+ transportToServerClosed = true
174
+ transportToClient.close().catch(onClientError)
175
+ }
176
+
177
+ transportToClient.onerror = onClientError
178
+ transportToServer.onerror = onServerError
179
+
180
+ function onClientError(error: Error) {
181
+ console.error('Error from local client:', error)
182
+ }
183
+
184
+ function onServerError(error: Error) {
185
+ console.error('Error from remote server:', error)
186
+ }
187
+ }
188
+
189
+ // Main function to run the proxy
190
+ async function runProxy(serverUrl: string, callbackPort: number) {
191
+ // Set up event emitter for auth flow
192
+ const events = new EventEmitter()
193
+
194
+ // Create the OAuth client provider
195
+ const authProvider = new NodeOAuthClientProvider(serverUrl, callbackPort)
196
+
197
+ // Create the STDIO transport
198
+ const localTransport = new StdioServerTransport()
199
+
200
+ // Set up an HTTP server to handle OAuth callback
201
+ let authCode: string | null = null
202
+ const app = express()
203
+
204
+ app.get('/oauth/callback', (req, res) => {
205
+ const code = req.query.code as string | undefined
206
+ if (!code) {
207
+ res.status(400).send('Error: No authorization code received')
208
+ return
209
+ }
210
+
211
+ authCode = code
212
+ res.send('Authorization successful! You may close this window and return to the CLI.')
213
+
214
+ // Notify main flow that auth code is available
215
+ events.emit('auth-code-received', code)
216
+ })
217
+
218
+ const httpServer = app.listen(callbackPort, () => {
219
+ console.error(`OAuth callback server running at http://localhost:${callbackPort}`)
220
+ })
221
+
222
+ // Function to wait for auth code
223
+ const waitForAuthCode = (): Promise<string> => {
224
+ return new Promise((resolve) => {
225
+ if (authCode) {
226
+ resolve(authCode)
227
+ return
228
+ }
229
+
230
+ events.once('auth-code-received', (code) => {
231
+ resolve(code)
232
+ })
233
+ })
234
+ }
235
+
236
+ // Function to create and connect to remote server, handling auth
237
+ const connectToRemoteServer = async (): Promise<SSEClientTransport> => {
238
+ console.error('Connecting to remote server:', serverUrl)
239
+ const url = new URL(serverUrl)
240
+ const transport = new SSEClientTransport(url, { authProvider })
241
+
242
+ try {
243
+ await transport.start()
244
+ console.error('Connected to remote server')
245
+ return transport
246
+ } catch (error) {
247
+ if (error instanceof UnauthorizedError || (error instanceof Error && error.message.includes('Unauthorized'))) {
248
+ console.error('Authentication required. Waiting for authorization...')
249
+
250
+ // Wait for the authorization code from the callback
251
+ const code = await waitForAuthCode()
252
+
253
+ try {
254
+ console.error('Completing authorization...')
255
+ await transport.finishAuth(code)
256
+
257
+ // Create a new transport after auth
258
+ const newTransport = new SSEClientTransport(url, { authProvider })
259
+ await newTransport.start()
260
+ console.error('Connected to remote server after authentication')
261
+ return newTransport
262
+ } catch (authError) {
263
+ console.error('Authorization error:', authError)
264
+ throw authError
265
+ }
266
+ } else {
267
+ console.error('Connection error:', error)
268
+ throw error
269
+ }
270
+ }
271
+ }
272
+
273
+ try {
274
+ // Start local server
275
+ // await server.connect(serverTransport)
276
+
277
+ // Connect to remote server
278
+ const remoteTransport = await connectToRemoteServer()
279
+
280
+ // Set up bidirectional proxy
281
+ mcpProxy({
282
+ transportToClient: localTransport,
283
+ transportToServer: remoteTransport,
284
+ })
285
+
286
+ await localTransport.start()
287
+ console.error('Local STDIO server running')
288
+
289
+ console.error('Proxy established successfully')
290
+ console.error('Press Ctrl+C to exit')
291
+
292
+ // Handle shutdown
293
+ process.on('SIGINT', async () => {
294
+ console.error('\nShutting down proxy...')
295
+ await remoteTransport.close()
296
+ await localTransport.close()
297
+ httpServer.close()
298
+ process.exit(0)
299
+ })
300
+
301
+ // Keep the process alive
302
+ process.stdin.resume()
303
+ } catch (error) {
304
+ console.error('Fatal error:', error)
305
+ httpServer.close()
306
+ process.exit(1)
307
+ }
308
+ }
309
+
310
+ // Parse command-line arguments
311
+ const args = process.argv.slice(2)
312
+ const serverUrl = args[0]
313
+ const callbackPort = args[1] ? parseInt(args[1]) : 3334
314
+
315
+ if (!serverUrl || !serverUrl.startsWith('https://')) {
316
+ console.error('Usage: npx tsx sse-auth-proxy.ts <https://server-url> [callback-port]')
317
+ process.exit(1)
318
+ }
319
+
320
+ runProxy(serverUrl, callbackPort).catch((error) => {
321
+ console.error('Fatal error:', error)
322
+ process.exit(1)
323
+ })
package/tsconfig.json ADDED
@@ -0,0 +1,17 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "Node16",
5
+ "moduleResolution": "Node16",
6
+ "outDir": "./build",
7
+ "rootDir": "./src",
8
+ "strict": true,
9
+ "esModuleInterop": true,
10
+ "lib": ["ES2022"],
11
+ "types": ["node"],
12
+ "forceConsistentCasingInFileNames": true,
13
+ "resolveJsonModule": true
14
+ },
15
+ "include": ["*.ts","src/**/*"],
16
+ "exclude": ["node_modules", "packages", "**/*.spec.ts"]
17
+ }