Skip to content

Commit 74307ae

Browse files
Saoudrizwan/add local (RooCodeInc#2637)
* Add local mcp servers tab * Remove form * docs links * changeset * punctuation * Fix max width --------- Co-authored-by: Saoud Rizwan <[email protected]>
1 parent 6f20321 commit 74307ae

File tree

6 files changed

+119
-33
lines changed

6 files changed

+119
-33
lines changed

.changeset/old-dots-peel.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"claude-dev": minor
3+
---
4+
5+
Added a tab for configuring local servers and documentation links

webview-ui/src/components/mcp/McpView.tsx

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import McpResourceRow from "./McpResourceRow"
1919
import McpToolRow from "./McpToolRow"
2020
import DangerButton from "../common/DangerButton"
2121
import AddRemoteServerForm from "./tabs/AddRemoteServerForm"
22+
import AddLocalServerForm from "./tabs/AddLocalServerForm"
2223

2324
type McpViewProps = {
2425
onDone: () => void
@@ -27,6 +28,7 @@ type McpViewProps = {
2728
const McpView = ({ onDone }: McpViewProps) => {
2829
const { mcpServers: servers, mcpMarketplaceEnabled } = useExtensionState()
2930
const [activeTab, setActiveTab] = useState(mcpMarketplaceEnabled ? "marketplace" : "installed")
31+
const [activeSubTab, setActiveSubTab] = useState("remote")
3032

3133
const handleTabChange = (tab: string) => {
3234
setActiveTab(tab)
@@ -83,7 +85,7 @@ const McpView = ({ onDone }: McpViewProps) => {
8385
</TabButton>
8486
)}
8587
<TabButton isActive={activeTab === "addRemote"} onClick={() => handleTabChange("addRemote")}>
86-
Remote Servers
88+
Add Server
8789
</TabButton>
8890
<TabButton isActive={activeTab === "installed"} onClick={() => handleTabChange("installed")}>
8991
Installed
@@ -93,7 +95,33 @@ const McpView = ({ onDone }: McpViewProps) => {
9395
{/* Content container */}
9496
<div style={{ width: "100%" }}>
9597
{mcpMarketplaceEnabled && activeTab === "marketplace" && <McpMarketplaceView />}
96-
{activeTab === "addRemote" && <AddRemoteServerForm onServerAdded={() => handleTabChange("installed")} />}
98+
{activeTab === "addRemote" && (
99+
<div style={{ padding: "5px 0 0 0" }}>
100+
<div
101+
style={{
102+
display: "flex",
103+
gap: "1px",
104+
padding: "0 20px 0 20px",
105+
borderBottom: "1px solid var(--vscode-panel-border)",
106+
}}>
107+
<TabButton isActive={activeSubTab === "remote"} onClick={() => setActiveSubTab("remote")}>
108+
Remote (SSE)
109+
</TabButton>
110+
<TabButton isActive={activeSubTab === "local"} onClick={() => setActiveSubTab("local")}>
111+
Local (Command)
112+
</TabButton>
113+
</div>
114+
115+
<div>
116+
{activeSubTab === "remote" && (
117+
<AddRemoteServerForm onServerAdded={() => handleTabChange("installed")} />
118+
)}
119+
{activeSubTab === "local" && (
120+
<AddLocalServerForm onServerAdded={() => handleTabChange("installed")} />
121+
)}
122+
</div>
123+
</div>
124+
)}
97125
{activeTab === "installed" && (
98126
<div style={{ padding: "16px 20px" }}>
99127
<div
@@ -153,8 +181,7 @@ const McpView = ({ onDone }: McpViewProps) => {
153181
onClick={() => {
154182
vscode.postMessage({ type: "openMcpSettings" })
155183
}}>
156-
<span className="codicon codicon-server" style={{ marginRight: "6px" }}></span>
157-
Configure MCP Servers
184+
Edit Configuration
158185
</VSCodeButton>
159186

160187
<div style={{ textAlign: "center" }}>
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import { VSCodeButton, VSCodeLink } from "@vscode/webview-ui-toolkit/react"
2+
3+
import { vscode } from "../../../utils/vscode"
4+
import styled from "styled-components"
5+
import { LINKS } from "../../../constants"
6+
7+
type AddLocalServerFormProps = {
8+
onServerAdded: () => void
9+
}
10+
11+
const AddLocalServerForm = ({ onServerAdded }: AddLocalServerFormProps) => {
12+
return (
13+
<FormContainer>
14+
<div className="text-[var(--vscode-foreground)]">
15+
Add a local MCP server by configuring it in <code>cline_mcp_settings.json</code>. You'll need to specify the
16+
server name, command, arguments, and any required environment variables in the JSON configuration. Learn more
17+
<VSCodeLink href={LINKS.DOCUMENTATION.LOCAL_MCP_SERVER_DOCS} style={{ display: "inline" }}>
18+
here.
19+
</VSCodeLink>
20+
</div>
21+
22+
<VSCodeButton
23+
appearance="primary"
24+
style={{ width: "100%", marginBottom: "5px", marginTop: 8 }}
25+
onClick={() => {
26+
vscode.postMessage({ type: "openMcpSettings" })
27+
}}>
28+
Open cline_mcp_settings.json
29+
</VSCodeButton>
30+
</FormContainer>
31+
)
32+
}
33+
34+
const FormContainer = styled.div`
35+
padding: 16px 20px;
36+
display: flex;
37+
flex-direction: column;
38+
gap: 8px;
39+
`
40+
41+
export default AddLocalServerForm

webview-ui/src/components/mcp/tabs/AddRemoteServerForm.tsx

Lines changed: 35 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
import { useCallback, useEffect, useRef, useState } from "react"
1+
import { useCallback, useRef, useState } from "react"
22
import { vscode } from "../../../utils/vscode"
3-
import { VSCodeButton } from "@vscode/webview-ui-toolkit/react"
3+
import { VSCodeButton, VSCodeLink, VSCodeTextField } from "@vscode/webview-ui-toolkit/react"
44
import { useEvent } from "react-use"
5-
5+
import { LINKS } from "../../../constants"
66
const AddRemoteServerForm = ({ onServerAdded }: { onServerAdded: () => void }) => {
77
const [serverName, setServerName] = useState("")
88
const [serverUrl, setServerUrl] = useState("")
@@ -79,48 +79,46 @@ const AddRemoteServerForm = ({ onServerAdded }: { onServerAdded: () => void }) =
7979

8080
return (
8181
<div className="p-4 px-5">
82-
<div className="text-[var(--vscode-foreground)] text-sm mb-4 mt-1 max-w-lg">
83-
Add a remote MCP server by providing a name and its URL endpoint.
82+
<div className="text-[var(--vscode-foreground)] mb-2">
83+
Add a remote MCP server by providing a name and its URL endpoint. Learn more{" "}
84+
<VSCodeLink href={LINKS.DOCUMENTATION.REMOTE_MCP_SERVER_DOCS} style={{ display: "inline" }}>
85+
here.
86+
</VSCodeLink>
8487
</div>
8588

8689
<form onSubmit={handleSubmit}>
87-
{error && (
88-
<div className="text-[var(--vscode-testing-iconFailed)] mb-3 p-2 rounded bg-[var(--vscode-inputValidation-warningBackground)] border border-[var(--vscode-inputValidation-warningBorder)]">
89-
{error}
90-
</div>
91-
)}
92-
93-
<div className="mb-4 mr-4">
94-
<label className="block mb-1">Server Name</label>
95-
<input
96-
type="text"
90+
<div className="mb-2">
91+
<VSCodeTextField
9792
value={serverName}
9893
onChange={(e) => {
99-
setServerName(e.target.value)
94+
setServerName((e.target as HTMLInputElement).value)
10095
setError("")
10196
}}
10297
disabled={isSubmitting}
103-
className="w-full max-w-md mr-4 p-2 bg-[var(--vscode-input-background)] text-[var(--vscode-input-foreground)] border border-[var(--vscode-input-border)] rounded"
104-
/>
98+
className="w-full"
99+
placeholder="mcp-server">
100+
Server Name
101+
</VSCodeTextField>
105102
</div>
106103

107-
<div className="mb-4 mr-4">
108-
<label className="block mb-1">Server URL</label>
109-
<input
110-
type="text"
104+
<div className="mb-2">
105+
<VSCodeTextField
111106
value={serverUrl}
112107
onChange={(e) => {
113-
setServerUrl(e.target.value)
108+
setServerUrl((e.target as HTMLInputElement).value)
114109
setError("")
115110
}}
116111
disabled={isSubmitting}
117-
placeholder="https://example.com/mcp-sse"
118-
className="w-full max-w-md mr-4 p-2 bg-[var(--vscode-input-background)] text-[var(--vscode-input-foreground)] border border-[var(--vscode-input-border)] rounded"
119-
/>
112+
placeholder="https://example.com/mcp-server"
113+
className="w-full mr-4">
114+
Server URL
115+
</VSCodeTextField>
120116
</div>
121117

122-
<div className="flex items-center mt-3">
123-
<VSCodeButton type="submit" disabled={isSubmitting}>
118+
{error && <div className="mb-3 text-[var(--vscode-errorForeground)]">{error}</div>}
119+
120+
<div className="flex items-center mt-3 w-full">
121+
<VSCodeButton type="submit" disabled={isSubmitting} className="w-full">
124122
{isSubmitting ? "Adding..." : "Add Server"}
125123
</VSCodeButton>
126124

@@ -130,6 +128,15 @@ const AddRemoteServerForm = ({ onServerAdded }: { onServerAdded: () => void }) =
130128
</div>
131129
)}
132130
</div>
131+
132+
<VSCodeButton
133+
appearance="secondary"
134+
style={{ width: "100%", marginBottom: "5px", marginTop: 15 }}
135+
onClick={() => {
136+
vscode.postMessage({ type: "openMcpSettings" })
137+
}}>
138+
Edit Configuration
139+
</VSCodeButton>
133140
</form>
134141
</div>
135142
)

webview-ui/src/components/settings/ApiOptions.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1212,7 +1212,7 @@ const ApiOptions = ({ showModelOptions, apiErrorMessage, modelIdErrorMessage, is
12121212
style={{
12131213
fontSize: "12px",
12141214
marginTop: "5px",
1215-
color: "var(--vscode-charts-green)",
1215+
color: "var(--vscode-descriptionForeground)",
12161216
}}>
12171217
Extended thinking is available for models as Sonnet-3-7, o3-mini, Deepseek R1, etc. More info on{" "}
12181218
<VSCodeLink

webview-ui/src/constants.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
export const LINKS = {
2+
DOCUMENTATION: {
3+
REMOTE_MCP_SERVER_DOCS: "https://docs.cline.bot/mcp-servers/connecting-to-a-remote-server",
4+
LOCAL_MCP_SERVER_DOCS: "https://docs.cline.bot/mcp-servers/configuring-mcp-servers#editing-mcp-settings-files",
5+
},
6+
}

0 commit comments

Comments
 (0)