@lobehub/chat 1.84.2 → 1.84.3

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/CHANGELOG.md CHANGED
@@ -2,6 +2,33 @@
2
2
 
3
3
  # Changelog
4
4
 
5
+ ### [Version 1.84.3](https://github.com/lobehub/lobe-chat/compare/v1.84.2...v1.84.3)
6
+
7
+ <sup>Released on **2025-04-28**</sup>
8
+
9
+ #### 🐛 Bug Fixes
10
+
11
+ - **misc**: Fix mcp server stdio spawn ENOENT in electron bundle, Fix mobile agent settings and textarea scroll, Remove `gpt-4o-search-preview` unsupported parameters.
12
+
13
+ <br/>
14
+
15
+ <details>
16
+ <summary><kbd>Improvements and Fixes</kbd></summary>
17
+
18
+ #### What's fixed
19
+
20
+ - **misc**: Fix mcp server stdio spawn ENOENT in electron bundle, closes [#7616](https://github.com/lobehub/lobe-chat/issues/7616) ([e85d59b](https://github.com/lobehub/lobe-chat/commit/e85d59b))
21
+ - **misc**: Fix mobile agent settings and textarea scroll, closes [#7618](https://github.com/lobehub/lobe-chat/issues/7618) ([c45f2b0](https://github.com/lobehub/lobe-chat/commit/c45f2b0))
22
+ - **misc**: Remove `gpt-4o-search-preview` unsupported parameters, closes [#7586](https://github.com/lobehub/lobe-chat/issues/7586) ([d2060ca](https://github.com/lobehub/lobe-chat/commit/d2060ca))
23
+
24
+ </details>
25
+
26
+ <div align="right">
27
+
28
+ [![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
29
+
30
+ </div>
31
+
5
32
  ### [Version 1.84.2](https://github.com/lobehub/lobe-chat/compare/v1.84.1...v1.84.2)
6
33
 
7
34
  <sup>Released on **2025-04-28**</sup>
@@ -68,10 +68,14 @@ const config = {
68
68
  gatekeeperAssess: false,
69
69
  hardenedRuntime: true,
70
70
  notarize: true,
71
- target: [
72
- { arch: ['x64', 'arm64'], target: 'dmg' },
73
- { arch: ['x64', 'arm64'], target: 'zip' },
74
- ],
71
+ target:
72
+ // 降低构建时间,nightly 只打 arm64
73
+ isNightly
74
+ ? [{ arch: ['arm64'], target: 'dmg' }]
75
+ : [
76
+ { arch: ['x64', 'arm64'], target: 'dmg' },
77
+ { arch: ['x64', 'arm64'], target: 'zip' },
78
+ ],
75
79
  },
76
80
  npmRebuild: true,
77
81
  nsis: {
@@ -54,6 +54,7 @@
54
54
  "electron-store": "^8.2.0",
55
55
  "electron-vite": "^3.0.0",
56
56
  "execa": "^9.5.2",
57
+ "fix-path": "^4.0.0",
57
58
  "just-diff": "^6.0.2",
58
59
  "lodash": "^4.17.21",
59
60
  "pglite-server": "^0.1.4",
@@ -1,5 +1,8 @@
1
+ import fixPath from 'fix-path';
2
+
1
3
  import { App } from './core/App';
2
4
 
3
5
  const app = new App();
4
6
 
7
+ fixPath();
5
8
  app.bootstrap();
package/changelog/v1.json CHANGED
@@ -1,4 +1,13 @@
1
1
  [
2
+ {
3
+ "children": {
4
+ "fixes": [
5
+ "Fix mcp server stdio spawn ENOENT in electron bundle, Fix mobile agent settings and textarea scroll, Remove gpt-4o-search-preview unsupported parameters."
6
+ ]
7
+ },
8
+ "date": "2025-04-28",
9
+ "version": "1.84.3"
10
+ },
2
11
  {
3
12
  "children": {},
4
13
  "date": "2025-04-28",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lobehub/chat",
3
- "version": "1.84.2",
3
+ "version": "1.84.3",
4
4
  "description": "Lobe Chat - an open-source, high-performance chatbot framework that supports speech synthesis, multimodal, and extensible Function Call plugin system. Supports one-click free deployment of your private ChatGPT/LLM web application.",
5
5
  "keywords": [
6
6
  "framework",
@@ -146,7 +146,7 @@
146
146
  "@lobehub/chat-plugins-gateway": "^1.9.0",
147
147
  "@lobehub/icons": "^2.0.0",
148
148
  "@lobehub/tts": "^2.0.0",
149
- "@lobehub/ui": "^2.0.1",
149
+ "@lobehub/ui": "^2.0.5",
150
150
  "@modelcontextprotocol/sdk": "^1.10.1",
151
151
  "@neondatabase/serverless": "^1.0.0",
152
152
  "@next/third-parties": "^15.3.0",
@@ -27,8 +27,9 @@ const useStyles = createStyles(({ css, token }) => {
27
27
  position: absolute;
28
28
  inset-inline-start: 14px;
29
29
  `,
30
- expandTextArea: css`
30
+ textarea: css`
31
31
  flex: 1;
32
+ transition: none !important;
32
33
  `,
33
34
  };
34
35
  });
@@ -114,7 +115,7 @@ const MobileChatInputArea = forwardRef<TextAreaRef, MobileChatInputAreaProps>(
114
115
  >
115
116
  <TextArea
116
117
  autoSize={expand ? false : { maxRows: 6, minRows: 0 }}
117
- className={cx(expand && styles.expandTextArea)}
118
+ className={styles.textarea}
118
119
  onBlur={(e) => {
119
120
  onInput?.(e.target.value);
120
121
  setIsFocused(false);
@@ -1,10 +1,13 @@
1
1
  'use client';
2
2
 
3
+ import { memo } from 'react';
4
+
3
5
  import { useRegisterChatHotkeys } from '@/hooks/useHotkeys';
4
6
 
5
- const RegisterHotkeys = () => {
7
+ const RegisterHotkeys = memo(() => {
6
8
  useRegisterChatHotkeys();
7
- return null;
8
- };
9
+
10
+ return '';
11
+ });
9
12
 
10
13
  export default RegisterHotkeys;
@@ -7,22 +7,20 @@ import { memo, useState } from 'react';
7
7
  import { useTranslation } from 'react-i18next';
8
8
 
9
9
  import PageTitle from '@/components/PageTitle';
10
- import { INBOX_SESSION_ID } from '@/const/session';
10
+ import { useCategory } from '@/features/AgentSetting/AgentCategory/useCategory';
11
+ import AgentSettings from '@/features/AgentSetting/AgentSettings';
11
12
  import { useInitAgentConfig } from '@/hooks/useInitAgentConfig';
12
13
  import { useAgentStore } from '@/store/agent';
13
14
  import { agentSelectors } from '@/store/agent/selectors';
14
15
  import { ChatSettingsTabs } from '@/store/global/initialState';
15
- import { featureFlagsSelectors, useServerConfigStore } from '@/store/serverConfig';
16
16
  import { useSessionStore } from '@/store/session';
17
17
  import { sessionMetaSelectors } from '@/store/session/selectors';
18
18
 
19
- import AgentSettings from '../../../../../features/AgentSetting/AgentSettings';
20
-
21
19
  const EditPage = memo(() => {
22
20
  const { t } = useTranslation('setting');
23
21
  const [tab, setTab] = useState(ChatSettingsTabs.Prompt);
24
22
  const theme = useTheme();
25
-
23
+ const cateItems = useCategory();
26
24
  const [id, updateAgentMeta, title] = useSessionStore((s) => [
27
25
  s.activeId,
28
26
  s.updateSessionMeta,
@@ -36,39 +34,12 @@ const EditPage = memo(() => {
36
34
 
37
35
  const { isLoading } = useInitAgentConfig();
38
36
 
39
- const { enablePlugins } = useServerConfigStore(featureFlagsSelectors);
40
-
41
37
  return (
42
38
  <>
43
39
  <PageTitle title={t('header.sessionWithName', { name: title })} />
44
40
  <Tabs
45
41
  compact
46
- items={[
47
- {
48
- key: ChatSettingsTabs.Prompt,
49
- label: t('settingAgent.prompt.title'),
50
- },
51
- (id !== INBOX_SESSION_ID && {
52
- key: ChatSettingsTabs.Meta,
53
- label: t('settingAgent.title'),
54
- }) as any,
55
- {
56
- key: ChatSettingsTabs.Chat,
57
- label: t('settingChat.title'),
58
- },
59
- {
60
- key: ChatSettingsTabs.Modal,
61
- label: t('settingModel.title'),
62
- },
63
- {
64
- key: ChatSettingsTabs.TTS,
65
- label: t('settingTTS.title'),
66
- },
67
- (enablePlugins && {
68
- key: ChatSettingsTabs.Plugin,
69
- label: t('settingPlugin.title'),
70
- }) as any,
71
- ]}
42
+ items={cateItems as any}
72
43
  onChange={(value) => setTab(value as ChatSettingsTabs)}
73
44
  style={{
74
45
  borderBottom: `1px solid ${theme.colorBorderSecondary}`,
@@ -15,7 +15,7 @@ const useStyles = createStyles(({ token, css }) => ({
15
15
  position: relative;
16
16
  flex: none;
17
17
  height: 54px;
18
- background: ${token.colorBgContainer};
18
+ background: ${token.colorBgLayout};
19
19
  `,
20
20
  title: css`
21
21
  font-size: 18px;
@@ -52,6 +52,11 @@ const Header = memo<HeaderProps>(({ children, getContainer, title }) => {
52
52
  }
53
53
  />
54
54
  }
55
+ styles={{
56
+ left: {
57
+ padding: 0,
58
+ },
59
+ }}
55
60
  />
56
61
  <Drawer
57
62
  getContainer={getContainer}
@@ -61,7 +66,7 @@ const Header = memo<HeaderProps>(({ children, getContainer, title }) => {
61
66
  placement={'left'}
62
67
  rootStyle={{ position: 'absolute' }}
63
68
  style={{
64
- background: theme.colorBgContainer,
69
+ background: theme.colorBgLayout,
65
70
  borderRight: `1px solid ${theme.colorSplit}`,
66
71
  }}
67
72
  styles={{
@@ -2,12 +2,14 @@
2
2
 
3
3
  import { Tag } from '@lobehub/ui';
4
4
  import { ChatHeader } from '@lobehub/ui/mobile';
5
+ import { usePathname } from 'next/navigation';
5
6
  import { memo } from 'react';
6
7
  import { useTranslation } from 'react-i18next';
7
8
  import { Flexbox } from 'react-layout-kit';
8
9
 
9
10
  import { enableAuth } from '@/const/auth';
10
11
  import { useActiveSettingsKey } from '@/hooks/useActiveTabKey';
12
+ import { useProviderName } from '@/hooks/useProviderName';
11
13
  import { useQueryRoute } from '@/hooks/useQueryRoute';
12
14
  import { useShowMobileWorkspace } from '@/hooks/useShowMobileWorkspace';
13
15
  import { SettingsTabs } from '@/store/global/initialState';
@@ -21,6 +23,9 @@ const Header = memo(() => {
21
23
  const showMobileWorkspace = useShowMobileWorkspace();
22
24
  const activeSettingsKey = useActiveSettingsKey();
23
25
  const isSessionActive = useSessionStore((s) => !!s.activeId);
26
+ const pathname = usePathname();
27
+ const isProvider = pathname.includes('/settings/provider/');
28
+ const providerName = useProviderName(activeSettingsKey);
24
29
 
25
30
  const handleBackClick = () => {
26
31
  if (isSessionActive && showMobileWorkspace) {
@@ -29,13 +34,16 @@ const Header = memo(() => {
29
34
  router.push(enableAuth ? '/me/settings' : '/me');
30
35
  }
31
36
  };
37
+
32
38
  return (
33
39
  <ChatHeader
34
40
  center={
35
41
  <ChatHeader.Title
36
42
  title={
37
43
  <Flexbox align={'center'} gap={8} horizontal>
38
- <span style={{ lineHeight: 1.2 }}> {t(`tab.${activeSettingsKey}`)}</span>
44
+ <span style={{ lineHeight: 1.2 }}>
45
+ {isProvider ? providerName : t(`tab.${activeSettingsKey}`)}
46
+ </span>
39
47
  {activeSettingsKey === SettingsTabs.Sync && (
40
48
  <Tag bordered={false} color={'warning'}>
41
49
  {t('tab.experiment')}
@@ -10,7 +10,7 @@ const Layout = ({ children }: PropsWithChildren) => {
10
10
  return (
11
11
  <>
12
12
  <NProgress />
13
- <Flexbox horizontal width={'100%'}>
13
+ <Flexbox height={'100%'} horizontal width={'100%'}>
14
14
  <AgentMenu />
15
15
  <SettingContainer>{children}</SettingContainer>
16
16
  </Flexbox>
@@ -1,14 +1,7 @@
1
- 'use client';
2
-
3
- import { usePathname } from 'next/navigation';
4
1
  import { PropsWithChildren } from 'react';
5
2
 
6
- import ProviderMenu from '../AgentMenu';
7
-
8
3
  const Layout = ({ children }: PropsWithChildren) => {
9
- const pathname = usePathname();
10
-
11
- return pathname === '/settings/agent' ? <ProviderMenu mobile /> : children;
4
+ return children;
12
5
  };
13
6
 
14
7
  export default Layout;
@@ -1,38 +1,58 @@
1
1
  'use client';
2
2
 
3
+ import { Tabs } from '@lobehub/ui';
4
+ import { useTheme } from 'antd-style';
3
5
  import isEqual from 'fast-deep-equal';
4
6
  import { useQueryState } from 'nuqs';
5
7
  import { memo } from 'react';
6
8
 
7
9
  import { INBOX_SESSION_ID } from '@/const/session';
8
10
  import { AgentSettings } from '@/features/AgentSetting';
11
+ import { useCategory } from '@/features/AgentSetting/AgentCategory/useCategory';
9
12
  import { ChatSettingsTabs } from '@/store/global/initialState';
13
+ import { useServerConfigStore } from '@/store/serverConfig';
10
14
  import { useUserStore } from '@/store/user';
11
15
  import { settingsSelectors } from '@/store/user/selectors';
12
16
 
13
17
  const Page = memo(() => {
14
- const [tab] = useQueryState('tab', {
18
+ const cateItems = useCategory();
19
+ const [tab, setTab] = useQueryState('tab', {
15
20
  defaultValue: ChatSettingsTabs.Prompt,
16
21
  });
17
22
  const config = useUserStore(settingsSelectors.defaultAgentConfig, isEqual);
18
23
  const meta = useUserStore(settingsSelectors.defaultAgentMeta, isEqual);
19
24
  const [updateAgent] = useUserStore((s) => [s.updateDefaultAgent]);
20
25
  const isUserStateInit = useUserStore((s) => s.isUserStateInit);
26
+ const theme = useTheme();
27
+ const mobile = useServerConfigStore((s) => s.isMobile);
21
28
 
22
29
  return (
23
- <AgentSettings
24
- config={config}
25
- id={INBOX_SESSION_ID}
26
- loading={!isUserStateInit}
27
- meta={meta}
28
- onConfigChange={(config) => {
29
- updateAgent({ config });
30
- }}
31
- onMetaChange={(meta) => {
32
- updateAgent({ meta });
33
- }}
34
- tab={tab as ChatSettingsTabs}
35
- />
30
+ <>
31
+ {mobile && (
32
+ <Tabs
33
+ activeKey={tab}
34
+ compact
35
+ items={cateItems as any}
36
+ onChange={(value) => setTab(value as ChatSettingsTabs)}
37
+ style={{
38
+ borderBottom: `1px solid ${theme.colorBorderSecondary}`,
39
+ }}
40
+ />
41
+ )}
42
+ <AgentSettings
43
+ config={config}
44
+ id={INBOX_SESSION_ID}
45
+ loading={!isUserStateInit}
46
+ meta={meta}
47
+ onConfigChange={(config) => {
48
+ updateAgent({ config });
49
+ }}
50
+ onMetaChange={(meta) => {
51
+ updateAgent({ meta });
52
+ }}
53
+ tab={tab as ChatSettingsTabs}
54
+ />
55
+ </>
36
56
  );
37
57
  });
38
58
 
@@ -60,6 +60,7 @@ const Common = memo(() => {
60
60
  ),
61
61
  desc: t('danger.reset.desc'),
62
62
  label: t('danger.reset.title'),
63
+ layout: 'horizontal',
63
64
  minWidth: undefined,
64
65
  },
65
66
  ],
@@ -1,5 +1,6 @@
1
1
  'use client';
2
2
 
3
+ import { useTheme } from 'antd-style';
3
4
  import { Suspense, memo } from 'react';
4
5
  import { Flexbox } from 'react-layout-kit';
5
6
 
@@ -48,12 +49,21 @@ interface ModelListProps extends ProviderSettingsContextValue {
48
49
  const ModelList = memo<ModelListProps>(
49
50
  ({ id, showModelFetcher, sdkType, showAddNewModel, showDeployName, modelEditable = true }) => {
50
51
  const mobile = useIsMobile();
52
+ const theme = useTheme();
51
53
 
52
54
  return (
53
55
  <ProviderSettingsContext
54
56
  value={{ modelEditable, sdkType, showAddNewModel, showDeployName, showModelFetcher }}
55
57
  >
56
- <Flexbox gap={16} paddingInline={mobile ? 12 : 0}>
58
+ <Flexbox
59
+ gap={16}
60
+ paddingInline={mobile ? 12 : 0}
61
+ style={{
62
+ background: mobile ? theme.colorBgContainer : undefined,
63
+ paddingBottom: 16,
64
+ paddingTop: 8,
65
+ }}
66
+ >
57
67
  <ModelTitle
58
68
  provider={id}
59
69
  showAddNewModel={showAddNewModel}
@@ -64,6 +64,7 @@ const AdvancedActions = () => {
64
64
  </DataImporter>
65
65
  ),
66
66
  label: t('storage.actions.import.title'),
67
+ layout: 'horizontal',
67
68
  minWidth: undefined,
68
69
  },
69
70
  {
@@ -78,6 +79,7 @@ const AdvancedActions = () => {
78
79
  </Button>
79
80
  ),
80
81
  label: t('storage.actions.export.title'),
82
+ layout: 'horizontal',
81
83
  minWidth: undefined,
82
84
  },
83
85
  {
@@ -88,6 +90,7 @@ const AdvancedActions = () => {
88
90
  ),
89
91
  desc: t('danger.clear.desc'),
90
92
  label: t('danger.clear.title'),
93
+ layout: 'horizontal',
91
94
  minWidth: undefined,
92
95
  },
93
96
  ],
@@ -14,21 +14,21 @@ import {
14
14
  } from '@/features/ModelParamsControl';
15
15
  import { useAgentStore } from '@/store/agent';
16
16
  import { agentSelectors } from '@/store/agent/selectors';
17
+ import { useServerConfigStore } from '@/store/serverConfig';
17
18
 
18
19
  interface ParamsControlsProps {
19
20
  setUpdating: (updating: boolean) => void;
20
21
  }
21
22
  const ParamsControls = memo<ParamsControlsProps>(({ setUpdating }) => {
22
23
  const { t } = useTranslation('setting');
23
-
24
+ const mobile = useServerConfigStore((s) => s.isMobile);
24
25
  const updateAgentConfig = useAgentStore((s) => s.updateAgentConfig);
25
26
 
26
27
  const config = useAgentStore(agentSelectors.currentAgentConfig, isEqual);
27
28
 
28
- const items: FormItemProps[] = [
29
+ let items: FormItemProps[] = [
29
30
  {
30
31
  children: <Temperature />,
31
- desc: <Tag>temperature</Tag>,
32
32
  label: (
33
33
  <Flexbox align={'center'} gap={8} horizontal justify={'space-between'}>
34
34
  {t('settingModel.temperature.title')}
@@ -36,10 +36,10 @@ const ParamsControls = memo<ParamsControlsProps>(({ setUpdating }) => {
36
36
  </Flexbox>
37
37
  ),
38
38
  name: ['params', 'temperature'],
39
+ tag: 'temperature',
39
40
  },
40
41
  {
41
42
  children: <TopP />,
42
- desc: <Tag>top_p</Tag>,
43
43
  label: (
44
44
  <Flexbox gap={8} horizontal>
45
45
  {t('settingModel.topP.title')}
@@ -47,10 +47,10 @@ const ParamsControls = memo<ParamsControlsProps>(({ setUpdating }) => {
47
47
  </Flexbox>
48
48
  ),
49
49
  name: ['params', 'top_p'],
50
+ tag: 'top_p',
50
51
  },
51
52
  {
52
53
  children: <PresencePenalty />,
53
- desc: <Tag>presence_penalty</Tag>,
54
54
  label: (
55
55
  <Flexbox gap={8} horizontal>
56
56
  {t('settingModel.presencePenalty.title')}
@@ -58,10 +58,10 @@ const ParamsControls = memo<ParamsControlsProps>(({ setUpdating }) => {
58
58
  </Flexbox>
59
59
  ),
60
60
  name: ['params', 'presence_penalty'],
61
+ tag: 'presence_penalty',
61
62
  },
62
63
  {
63
64
  children: <FrequencyPenalty />,
64
- desc: <Tag>frequency_penalty</Tag>,
65
65
  label: (
66
66
  <Flexbox gap={8} horizontal>
67
67
  {t('settingModel.frequencyPenalty.title')}
@@ -69,6 +69,7 @@ const ParamsControls = memo<ParamsControlsProps>(({ setUpdating }) => {
69
69
  </Flexbox>
70
70
  ),
71
71
  name: ['params', 'frequency_penalty'],
72
+ tag: 'frequency_penalty',
72
73
  },
73
74
  ];
74
75
 
@@ -76,7 +77,9 @@ const ParamsControls = memo<ParamsControlsProps>(({ setUpdating }) => {
76
77
  <Form
77
78
  initialValues={config}
78
79
  itemMinWidth={200}
79
- items={items}
80
+ items={
81
+ mobile ? items : items.map(({ tag, ...item }) => ({ ...item, desc: <Tag>{tag}</Tag> }))
82
+ }
80
83
  itemsType={'flat'}
81
84
  onValuesChange={debounce(async (values) => {
82
85
  setUpdating(true);
@@ -84,6 +87,13 @@ const ParamsControls = memo<ParamsControlsProps>(({ setUpdating }) => {
84
87
  setUpdating(false);
85
88
  }, 500)}
86
89
  style={{ fontSize: 12 }}
90
+ styles={{
91
+ group: {
92
+ background: 'transparent',
93
+ paddingBottom: mobile ? 16 : 0,
94
+ paddingInline: 0,
95
+ },
96
+ }}
87
97
  variant={'borderless'}
88
98
  />
89
99
  );
@@ -107,6 +107,4 @@ export const useRegisterChatHotkeys = () => {
107
107
  enableScope(HotkeyScopeEnum.Chat);
108
108
  return () => disableScope(HotkeyScopeEnum.Chat);
109
109
  }, []);
110
-
111
- return null;
112
110
  };
@@ -32,6 +32,4 @@ export const useRegisterFilesHotkeys = () => {
32
32
  enableScope(HotkeyScopeEnum.Files);
33
33
  return () => disableScope(HotkeyScopeEnum.Files);
34
34
  }, []);
35
-
36
- return null;
37
35
  };
@@ -18,6 +18,17 @@ export const LobeOpenAI = LobeOpenAICompatibleFactory({
18
18
  return pruneReasoningPayload(payload) as any;
19
19
  }
20
20
 
21
+ if (model.includes('-search-')) {
22
+ return {
23
+ ...payload,
24
+ frequency_penalty: undefined,
25
+ presence_penalty: undefined,
26
+ stream: payload.stream ?? true,
27
+ temperature: undefined,
28
+ top_p: undefined,
29
+ };
30
+ }
31
+
21
32
  return { ...payload, stream: payload.stream ?? true };
22
33
  },
23
34
  },
@@ -1,5 +1,8 @@
1
1
  import { Client } from '@modelcontextprotocol/sdk/client/index.js';
2
- import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
2
+ import {
3
+ StdioClientTransport,
4
+ getDefaultEnvironment,
5
+ } from '@modelcontextprotocol/sdk/client/stdio.js';
3
6
  import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';
4
7
  import type { Transport } from '@modelcontextprotocol/sdk/shared/transport.d.ts';
5
8
  import debug from 'debug';
@@ -24,9 +27,14 @@ export class MCPClient {
24
27
  }
25
28
  case 'stdio': {
26
29
  log('Using Stdio transport with command: %s and args: %O', params.command, params.args);
30
+
27
31
  this.transport = new StdioClientTransport({
28
32
  args: params.args,
29
33
  command: params.command,
34
+ env: {
35
+ ...getDefaultEnvironment(),
36
+ ...params.env,
37
+ },
30
38
  });
31
39
  break;
32
40
  }
@@ -20,6 +20,7 @@ interface HttpMCPClientParams {
20
20
  interface StdioMCPParams {
21
21
  args: string[];
22
22
  command: string;
23
+ env?: Record<string, string>;
23
24
  name: string;
24
25
  type: 'stdio';
25
26
  }