@expandai/mcp-server 0.1.1 → 0.1.4

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/dist/main.cjs CHANGED
@@ -39,7 +39,7 @@ var S__namespace = /*#__PURE__*/_interopNamespace(S);
39
39
 
40
40
  // package.json
41
41
  var package_default = {
42
- version: "0.1.1"};
42
+ version: "0.1.4"};
43
43
  var ExpandDocs = ai.McpServer.resource({
44
44
  uri: "expand://about",
45
45
  name: "About expand.ai",
@@ -690,7 +690,7 @@ var ClientError = (tag, cause, response) => new ClientErrorImpl({
690
690
 
691
691
  // src/ExpandClient.ts
692
692
  var ExpandConfig = effect.Config.all({
693
- apiKey: effect.Config.redacted("EXPAND_API_KEY"),
693
+ apiKey: effect.Config.option(effect.Config.redacted("EXPAND_API_KEY")),
694
694
  baseUrl: effect.Config.withDefault(effect.Config.string("EXPAND_BASE_URL"), "https://api.expand.ai")
695
695
  });
696
696
  var ExpandClient = class extends effect.Effect.Service()("ExpandClient", {
@@ -698,11 +698,24 @@ var ExpandClient = class extends effect.Effect.Service()("ExpandClient", {
698
698
  scoped: effect.Effect.gen(function* () {
699
699
  const config = yield* ExpandConfig;
700
700
  const httpClient = yield* platform.HttpClient.HttpClient;
701
+ const requestHeaders = yield* effect.Effect.serviceOption(CurrentRequestHeaders);
702
+ yield* effect.Effect.logInfo(`ExpandClient connected to ${config.baseUrl}`);
701
703
  return make(httpClient, {
702
704
  transformClient: (client) => effect.Effect.succeed(
703
705
  client.pipe(
704
706
  platform.HttpClient.mapRequest(platform.HttpClientRequest.prependUrl(config.baseUrl)),
705
- platform.HttpClient.mapRequest(platform.HttpClientRequest.setHeader("x-expand-api-key", effect.Redacted.value(config.apiKey)))
707
+ platform.HttpClient.mapRequest((req) => {
708
+ if (effect.Option.isSome(requestHeaders)) {
709
+ const auth = requestHeaders.value["authorization"];
710
+ if (auth) {
711
+ return platform.HttpClientRequest.setHeader("authorization", auth)(req);
712
+ }
713
+ }
714
+ if (effect.Option.isSome(config.apiKey)) {
715
+ return platform.HttpClientRequest.setHeader("x-expand-api-key", effect.Redacted.value(config.apiKey.value))(req);
716
+ }
717
+ return req;
718
+ })
706
719
  )
707
720
  )
708
721
  });
@@ -765,6 +778,8 @@ var Fetch = class extends effect.Effect.Service()("Fetch", {
765
778
  scoped: effect.Effect.gen(function* () {
766
779
  const client = yield* ExpandClient;
767
780
  const fetch = effect.Effect.fn("Fetch.fetch")(function* ({ url, format, includeMeta }) {
781
+ const formatLabel = format instanceof SnippetsFormat ? "snippets" : format;
782
+ yield* effect.Effect.logDebug(`Fetching: ${url}`).pipe(effect.Effect.annotateLogs({ format: formatLabel, includeMeta }));
768
783
  const result = yield* client.fetch({
769
784
  url,
770
785
  select: {
@@ -776,6 +791,7 @@ var Fetch = class extends effect.Effect.Service()("Fetch", {
776
791
  }
777
792
  });
778
793
  const content = result.data.markdown ?? result.data.html ?? result.data.summary ?? result.data.snippets?.map((snippet) => `${snippet.text} (Score: ${snippet.score})`).join("\n") ?? "";
794
+ yield* effect.Effect.logDebug(`\u{1F4E4} Fetched successfully: ${result.data.response.url}`);
779
795
  return new FetchResult2({
780
796
  content,
781
797
  url: result.data.response.url,
@@ -787,28 +803,67 @@ var Fetch = class extends effect.Effect.Service()("Fetch", {
787
803
  }) {
788
804
  };
789
805
 
790
- // src/tools/index.ts
806
+ // src/Toolkit.ts
791
807
  var toolkit = ai.Toolkit.make(FetchTool);
792
808
  var ToolkitLayer = toolkit.toLayer(
793
809
  effect.Effect.gen(function* () {
810
+ yield* effect.Effect.logInfo("Registering tools: fetch");
794
811
  const fetchService = yield* Fetch;
795
812
  return toolkit.of({
796
813
  fetch: fetchService.fetch
797
814
  });
798
815
  })
799
816
  ).pipe(effect.Layer.provide(Fetch.Default), effect.Layer.provide(ExpandClient.Default), effect.Layer.provide(platformNode.NodeHttpClient.layerUndici));
800
- var ExpandTools = ai.McpServer.toolkit(toolkit).pipe(effect.Layer.provide(ToolkitLayer));
817
+ var ExpandToolKit = ai.McpServer.toolkit(toolkit).pipe(effect.Layer.provide(ToolkitLayer));
818
+
819
+ // src/Server.ts
820
+ var ServerInfo = {
821
+ name: "expandai-mcp-server",
822
+ version: package_default.version
823
+ };
824
+ var CurrentRequestHeaders = class extends effect.Context.Tag("CurrentRequestHeaders")() {
825
+ };
826
+ var makeServerLayer = (options = {}) => options.includeDocs ? effect.Layer.mergeAll(ExpandToolKit, ExpandDocs) : ExpandToolKit;
801
827
 
802
828
  // src/main.ts
803
- var enableDocs = effect.Config.withDefault(effect.Config.boolean("EXPAND_ENABLE_DOCS"), () => false);
829
+ var enableDocs = effect.Config.withDefault(effect.Config.boolean("EXPAND_ENABLE_DOCS"), false);
830
+ var logLevelConfig = effect.Config.withDefault(
831
+ effect.Config.literal("debug", "info", "warning", "error", "none")("LOG_LEVEL"),
832
+ "info"
833
+ );
834
+ var logLevelMap = {
835
+ debug: effect.LogLevel.Debug,
836
+ info: effect.LogLevel.Info,
837
+ warning: effect.LogLevel.Warning,
838
+ error: effect.LogLevel.Error,
839
+ none: effect.LogLevel.None
840
+ };
841
+ var startupBanner = `
842
+ \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557
843
+ \u2551 \u2551
844
+ \u2551 \u{1F310} expand.ai MCP Server \u2551
845
+ \u2551 \u2551
846
+ \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D`;
804
847
  var program = effect.Effect.gen(function* () {
805
848
  const docsEnabled = yield* enableDocs;
806
- const layers = docsEnabled ? effect.Layer.mergeAll(ExpandTools, ExpandDocs) : ExpandTools;
807
- yield* ai.McpServer.layerStdio({
808
- name: "expandai-mcp-server",
809
- version: package_default.version,
849
+ const logLevel = yield* logLevelConfig;
850
+ yield* effect.Effect.logInfo(startupBanner);
851
+ yield* effect.Effect.logInfo(`Starting v${ServerInfo.version}`);
852
+ yield* effect.Effect.logInfo(`Documentation resources: ${docsEnabled ? "enabled" : "disabled"}`);
853
+ const McpLayer = ai.McpServer.layerStdio({
854
+ ...ServerInfo,
810
855
  stdin: platformNode.NodeStream.stdin,
811
856
  stdout: platformNode.NodeSink.stdout
812
- }).pipe(effect.Layer.provide(layers), effect.Layer.provide(effect.Logger.minimumLogLevel(effect.LogLevel.None)), effect.Layer.launch);
857
+ }).pipe(effect.Layer.provide(makeServerLayer({ includeDocs: docsEnabled })));
858
+ const LifecycleLayer = effect.Layer.scopedDiscard(
859
+ effect.Effect.acquireRelease(
860
+ effect.Effect.logInfo("Server ready and listening on stdio"),
861
+ () => effect.Effect.logInfo("Server shutting down gracefully...")
862
+ )
863
+ );
864
+ yield* effect.Layer.merge(McpLayer, LifecycleLayer).pipe(
865
+ effect.Layer.provide(effect.Logger.minimumLogLevel(logLevelMap[logLevel])),
866
+ effect.Layer.launch
867
+ );
813
868
  });
814
869
  program.pipe(platformNode.NodeRuntime.runMain);
@@ -0,0 +1 @@
1
+ #!/usr/bin/env node
package/dist/main.d.ts ADDED
@@ -0,0 +1 @@
1
+ #!/usr/bin/env node
package/dist/main.js ADDED
@@ -0,0 +1,47 @@
1
+ #!/usr/bin/env node
2
+ import { ServerInfo, makeServerLayer } from './chunk-TUBB4OP4.js';
3
+ import { McpServer } from '@effect/ai';
4
+ import { NodeSink, NodeStream, NodeRuntime } from '@effect/platform-node';
5
+ import { Config, Effect, Layer, Logger, LogLevel } from 'effect';
6
+
7
+ var enableDocs = Config.withDefault(Config.boolean("EXPAND_ENABLE_DOCS"), false);
8
+ var logLevelConfig = Config.withDefault(
9
+ Config.literal("debug", "info", "warning", "error", "none")("LOG_LEVEL"),
10
+ "info"
11
+ );
12
+ var logLevelMap = {
13
+ debug: LogLevel.Debug,
14
+ info: LogLevel.Info,
15
+ warning: LogLevel.Warning,
16
+ error: LogLevel.Error,
17
+ none: LogLevel.None
18
+ };
19
+ var startupBanner = `
20
+ \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557
21
+ \u2551 \u2551
22
+ \u2551 \u{1F310} expand.ai MCP Server \u2551
23
+ \u2551 \u2551
24
+ \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D`;
25
+ var program = Effect.gen(function* () {
26
+ const docsEnabled = yield* enableDocs;
27
+ const logLevel = yield* logLevelConfig;
28
+ yield* Effect.logInfo(startupBanner);
29
+ yield* Effect.logInfo(`Starting v${ServerInfo.version}`);
30
+ yield* Effect.logInfo(`Documentation resources: ${docsEnabled ? "enabled" : "disabled"}`);
31
+ const McpLayer = McpServer.layerStdio({
32
+ ...ServerInfo,
33
+ stdin: NodeStream.stdin,
34
+ stdout: NodeSink.stdout
35
+ }).pipe(Layer.provide(makeServerLayer({ includeDocs: docsEnabled })));
36
+ const LifecycleLayer = Layer.scopedDiscard(
37
+ Effect.acquireRelease(
38
+ Effect.logInfo("Server ready and listening on stdio"),
39
+ () => Effect.logInfo("Server shutting down gracefully...")
40
+ )
41
+ );
42
+ yield* Layer.merge(McpLayer, LifecycleLayer).pipe(
43
+ Layer.provide(Logger.minimumLogLevel(logLevelMap[logLevel])),
44
+ Layer.launch
45
+ );
46
+ });
47
+ program.pipe(NodeRuntime.runMain);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@expandai/mcp-server",
3
- "version": "0.1.1",
3
+ "version": "0.1.4",
4
4
  "description": "MCP server for expand.ai - Give AI agents access to the web",
5
5
  "type": "module",
6
6
  "publishConfig": {
@@ -9,6 +9,14 @@
9
9
  "bin": {
10
10
  "expandai-mcp-server": "./dist/main.cjs"
11
11
  },
12
+ "exports": {
13
+ ".": "./dist/main.cjs",
14
+ "./Server": {
15
+ "types": "./dist/Server.d.ts",
16
+ "import": "./dist/Server.js",
17
+ "require": "./dist/Server.cjs"
18
+ }
19
+ },
12
20
  "files": [
13
21
  "dist",
14
22
  "src",
@@ -17,10 +25,13 @@
17
25
  ],
18
26
  "repository": {
19
27
  "type": "git",
20
- "url": "https://github.com/expandai/expandai-mcp-server.git"
28
+ "url": "git+https://github.com/expandai/expandai-mcp-server.git"
29
+ },
30
+ "bugs": {
31
+ "url": "https://github.com/expandai/expandai-mcp-server/issues"
21
32
  },
22
33
  "homepage": "https://expand.ai",
23
- "author": "expand.ai",
34
+ "author": "expand.ai <support@expand.ai>",
24
35
  "license": "Apache-2.0",
25
36
  "keywords": [
26
37
  "mcp",
@@ -1,9 +1,10 @@
1
1
  import { HttpClient, HttpClientRequest } from '@effect/platform'
2
- import { Config, Effect, Redacted } from 'effect'
3
- import * as GeneratedClient from './generated/ExpandClient.js'
2
+ import { Config, Effect, Option, Redacted } from 'effect'
3
+ import * as GeneratedClient from './Generated.js'
4
+ import { CurrentRequestHeaders } from './Server.js'
4
5
 
5
6
  export const ExpandConfig = Config.all({
6
- apiKey: Config.redacted('EXPAND_API_KEY'),
7
+ apiKey: Config.option(Config.redacted('EXPAND_API_KEY')),
7
8
  baseUrl: Config.withDefault(Config.string('EXPAND_BASE_URL'), 'https://api.expand.ai'),
8
9
  })
9
10
 
@@ -12,13 +13,27 @@ export class ExpandClient extends Effect.Service<ExpandClient>()('ExpandClient',
12
13
  scoped: Effect.gen(function* () {
13
14
  const config = yield* ExpandConfig
14
15
  const httpClient = yield* HttpClient.HttpClient
16
+ const requestHeaders = yield* Effect.serviceOption(CurrentRequestHeaders)
17
+
18
+ yield* Effect.logInfo(`ExpandClient connected to ${config.baseUrl}`)
15
19
 
16
20
  return GeneratedClient.make(httpClient, {
17
21
  transformClient: (client) =>
18
22
  Effect.succeed(
19
23
  client.pipe(
20
24
  HttpClient.mapRequest(HttpClientRequest.prependUrl(config.baseUrl)),
21
- HttpClient.mapRequest(HttpClientRequest.setHeader('x-expand-api-key', Redacted.value(config.apiKey))),
25
+ HttpClient.mapRequest((req) => {
26
+ if (Option.isSome(requestHeaders)) {
27
+ const auth = requestHeaders.value['authorization']
28
+ if (auth) {
29
+ return HttpClientRequest.setHeader('authorization', auth)(req)
30
+ }
31
+ }
32
+ if (Option.isSome(config.apiKey)) {
33
+ return HttpClientRequest.setHeader('x-expand-api-key', Redacted.value(config.apiKey.value))(req)
34
+ }
35
+ return req
36
+ }),
22
37
  ),
23
38
  ),
24
39
  })
@@ -1,7 +1,7 @@
1
1
  import { Tool } from '@effect/ai'
2
2
  import { Effect, Schema } from 'effect'
3
- import { ExpandClient } from '../ExpandClient.js'
4
- import { PageMeta } from '../generated/ExpandClient.js'
3
+ import { ExpandClient } from './ExpandClient.js'
4
+ import { PageMeta } from './Generated.js'
5
5
 
6
6
  export class SnippetsFormat extends Schema.Class<SnippetsFormat>('SnippetsFormat')({
7
7
  query: Schema.String.annotations({
@@ -64,6 +64,9 @@ export class Fetch extends Effect.Service<Fetch>()('Fetch', {
64
64
  const client = yield* ExpandClient
65
65
 
66
66
  const fetch = Effect.fn('Fetch.fetch')(function* ({ url, format, includeMeta }: FetchParams) {
67
+ const formatLabel = format instanceof SnippetsFormat ? 'snippets' : format
68
+ yield* Effect.logDebug(`Fetching: ${url}`).pipe(Effect.annotateLogs({ format: formatLabel, includeMeta }))
69
+
67
70
  const result = yield* client.fetch({
68
71
  url,
69
72
  select: {
@@ -82,6 +85,8 @@ export class Fetch extends Effect.Service<Fetch>()('Fetch', {
82
85
  result.data.snippets?.map((snippet) => `${snippet.text} (Score: ${snippet.score})`).join('\n') ??
83
86
  ''
84
87
 
88
+ yield* Effect.logDebug(`📤 Fetched successfully: ${result.data.response.url}`)
89
+
85
90
  return new FetchResult({
86
91
  content,
87
92
  url: result.data.response.url,
package/src/Server.ts ADDED
@@ -0,0 +1,17 @@
1
+ import { Context, Layer } from 'effect'
2
+ import packageJson from '../package.json' with { type: 'json' }
3
+ import { ExpandDocs } from './ExpandDocs.js'
4
+ import { ExpandToolKit } from './Toolkit.js'
5
+
6
+ export const ServerInfo = {
7
+ name: 'expandai-mcp-server',
8
+ version: packageJson.version,
9
+ } as const
10
+
11
+ export class CurrentRequestHeaders extends Context.Tag('CurrentRequestHeaders')<
12
+ CurrentRequestHeaders,
13
+ Record<string, string>
14
+ >() {}
15
+
16
+ export const makeServerLayer = (options: { readonly includeDocs?: boolean } = {}) =>
17
+ options.includeDocs ? Layer.mergeAll(ExpandToolKit, ExpandDocs) : ExpandToolKit
package/src/Toolkit.ts ADDED
@@ -0,0 +1,23 @@
1
+ import { McpServer, Toolkit } from '@effect/ai'
2
+ import { NodeHttpClient } from '@effect/platform-node'
3
+ import { Effect, Layer } from 'effect'
4
+ import { ExpandClient } from './ExpandClient.js'
5
+ import { Fetch, FetchTool } from './Fetch.js'
6
+
7
+ const toolkit = Toolkit.make(FetchTool)
8
+
9
+ const ToolkitLayer = toolkit
10
+ .toLayer(
11
+ Effect.gen(function* () {
12
+ yield* Effect.logInfo('Registering tools: fetch')
13
+
14
+ const fetchService = yield* Fetch
15
+
16
+ return toolkit.of({
17
+ fetch: fetchService.fetch,
18
+ })
19
+ }),
20
+ )
21
+ .pipe(Layer.provide(Fetch.Default), Layer.provide(ExpandClient.Default), Layer.provide(NodeHttpClient.layerUndici))
22
+
23
+ export const ExpandToolKit = McpServer.toolkit(toolkit).pipe(Layer.provide(ToolkitLayer))
package/src/main.ts CHANGED
@@ -2,23 +2,54 @@
2
2
  import { McpServer } from '@effect/ai'
3
3
  import { NodeRuntime, NodeSink, NodeStream } from '@effect/platform-node'
4
4
  import { Config, Effect, Layer, Logger, LogLevel } from 'effect'
5
- import packageJson from '../package.json' with { type: 'json' }
6
- import { ExpandDocs } from './resources/ExpandDocs.js'
7
- import { ExpandTools } from './tools/index.js'
5
+ import { makeServerLayer, ServerInfo } from './Server.js'
8
6
 
9
- const enableDocs = Config.withDefault(Config.boolean('EXPAND_ENABLE_DOCS'), () => false)
7
+ const enableDocs = Config.withDefault(Config.boolean('EXPAND_ENABLE_DOCS'), false)
8
+
9
+ const logLevelConfig = Config.withDefault(
10
+ Config.literal('debug', 'info', 'warning', 'error', 'none')('LOG_LEVEL'),
11
+ 'info',
12
+ )
13
+
14
+ const logLevelMap = {
15
+ debug: LogLevel.Debug,
16
+ info: LogLevel.Info,
17
+ warning: LogLevel.Warning,
18
+ error: LogLevel.Error,
19
+ none: LogLevel.None,
20
+ } as const
21
+
22
+ const startupBanner = `
23
+ ╔═══════════════════════════════════════════════════╗
24
+ ║ ║
25
+ ║ 🌐 expand.ai MCP Server ║
26
+ ║ ║
27
+ ╚═══════════════════════════════════════════════════╝`
10
28
 
11
29
  const program = Effect.gen(function* () {
12
30
  const docsEnabled = yield* enableDocs
31
+ const logLevel = yield* logLevelConfig
13
32
 
14
- const layers = docsEnabled ? Layer.mergeAll(ExpandTools, ExpandDocs) : ExpandTools
33
+ yield* Effect.logInfo(startupBanner)
34
+ yield* Effect.logInfo(`Starting v${ServerInfo.version}`)
35
+ yield* Effect.logInfo(`Documentation resources: ${docsEnabled ? 'enabled' : 'disabled'}`)
15
36
 
16
- yield* McpServer.layerStdio({
17
- name: 'expandai-mcp-server',
18
- version: packageJson.version,
37
+ const McpLayer = McpServer.layerStdio({
38
+ ...ServerInfo,
19
39
  stdin: NodeStream.stdin,
20
40
  stdout: NodeSink.stdout,
21
- }).pipe(Layer.provide(layers), Layer.provide(Logger.minimumLogLevel(LogLevel.None)), Layer.launch)
41
+ }).pipe(Layer.provide(makeServerLayer({ includeDocs: docsEnabled })))
42
+
43
+ const LifecycleLayer = Layer.scopedDiscard(
44
+ Effect.acquireRelease(Effect.logInfo('Server ready and listening on stdio'), () =>
45
+ Effect.logInfo('Server shutting down gracefully...'),
46
+ ),
47
+ )
48
+
49
+ yield* Layer.merge(McpLayer, LifecycleLayer).pipe(
50
+ Layer.provide(Logger.minimumLogLevel(logLevelMap[logLevel])),
51
+ Layer.launch,
52
+ )
22
53
  })
23
54
 
24
55
  program.pipe(NodeRuntime.runMain)
@@ -1,33 +0,0 @@
1
- import { McpServer, Toolkit } from '@effect/ai'
2
- import { NodeHttpClient } from '@effect/platform-node'
3
- import { Effect, Layer } from 'effect'
4
- import { ExpandClient } from '../ExpandClient.js'
5
- import { Fetch, FetchTool } from './Fetch.js'
6
-
7
- // =============================================================================
8
- // Toolkit (add more tools here)
9
- // =============================================================================
10
-
11
- const toolkit = Toolkit.make(FetchTool)
12
-
13
- // =============================================================================
14
- // Toolkit Layer
15
- // =============================================================================
16
-
17
- const ToolkitLayer = toolkit
18
- .toLayer(
19
- Effect.gen(function* () {
20
- const fetchService = yield* Fetch
21
-
22
- return toolkit.of({
23
- fetch: fetchService.fetch,
24
- })
25
- }),
26
- )
27
- .pipe(Layer.provide(Fetch.Default), Layer.provide(ExpandClient.Default), Layer.provide(NodeHttpClient.layerUndici))
28
-
29
- // =============================================================================
30
- // Export
31
- // =============================================================================
32
-
33
- export const ExpandTools = McpServer.toolkit(toolkit).pipe(Layer.provide(ToolkitLayer))
File without changes
File without changes