mirror of
https://github.com/pacnpal/Roo-Code.git
synced 2025-12-20 20:31:37 -05:00
Add mock data and gui
This commit is contained in:
@@ -1,10 +1,120 @@
|
|||||||
import { VSCodeButton } from "@vscode/webview-ui-toolkit/react"
|
import {
|
||||||
|
VSCodeButton,
|
||||||
|
VSCodeDivider,
|
||||||
|
VSCodeTextArea,
|
||||||
|
VSCodeTextField,
|
||||||
|
VSCodeTag,
|
||||||
|
VSCodePanelTab,
|
||||||
|
VSCodePanelView,
|
||||||
|
VSCodeDataGrid,
|
||||||
|
VSCodeDataGridRow,
|
||||||
|
VSCodeDataGridCell,
|
||||||
|
VSCodePanels,
|
||||||
|
} from "@vscode/webview-ui-toolkit/react"
|
||||||
|
import { useState } from "react"
|
||||||
|
|
||||||
|
type McpServer = {
|
||||||
|
name: string
|
||||||
|
config: string // JSON config
|
||||||
|
status: "connected" | "connecting" | "disconnected"
|
||||||
|
error?: string
|
||||||
|
tools?: any[] // We'll type this properly later
|
||||||
|
resources?: any[] // We'll type this properly later
|
||||||
|
}
|
||||||
|
|
||||||
type McpViewProps = {
|
type McpViewProps = {
|
||||||
onDone: () => void
|
onDone: () => void
|
||||||
}
|
}
|
||||||
|
|
||||||
const McpView = ({ onDone }: McpViewProps) => {
|
const McpView = ({ onDone }: McpViewProps) => {
|
||||||
|
const [isAdding, setIsAdding] = useState(false)
|
||||||
|
const [servers, setServers] = useState<McpServer[]>([
|
||||||
|
// Add some mock servers for testing
|
||||||
|
{
|
||||||
|
name: "local-tools",
|
||||||
|
config: JSON.stringify({
|
||||||
|
mcpServers: {
|
||||||
|
"local-tools": {
|
||||||
|
command: "npx",
|
||||||
|
args: ["-y", "@modelcontextprotocol/server-tools"],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
status: "connected",
|
||||||
|
tools: [
|
||||||
|
{
|
||||||
|
name: "execute_command",
|
||||||
|
description: "Run a shell command on the local system",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "read_file",
|
||||||
|
description: "Read contents of a file from the filesystem",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "postgres-db",
|
||||||
|
config: JSON.stringify({
|
||||||
|
mcpServers: {
|
||||||
|
"postgres-db": {
|
||||||
|
command: "npx",
|
||||||
|
args: ["-y", "@modelcontextprotocol/server-postgres", "postgresql://localhost/mydb"],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
status: "disconnected",
|
||||||
|
error: "Failed to connect to database: Connection refused",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "github-tools",
|
||||||
|
config: JSON.stringify({
|
||||||
|
mcpServers: {
|
||||||
|
"github-tools": {
|
||||||
|
command: "npx",
|
||||||
|
args: ["-y", "@modelcontextprotocol/server-github"],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
status: "connecting",
|
||||||
|
resources: [
|
||||||
|
{
|
||||||
|
uri: "github://repo/issues",
|
||||||
|
name: "Repository Issues",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
uri: "github://repo/pulls",
|
||||||
|
name: "Pull Requests",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
])
|
||||||
|
const [configInput, setConfigInput] = useState("")
|
||||||
|
|
||||||
|
const handleAddServer = () => {
|
||||||
|
try {
|
||||||
|
const config = JSON.parse(configInput)
|
||||||
|
const serverName = Object.keys(config.mcpServers)[0]
|
||||||
|
|
||||||
|
setServers((prev) => [
|
||||||
|
...prev,
|
||||||
|
{
|
||||||
|
name: serverName,
|
||||||
|
config: configInput,
|
||||||
|
status: "connecting",
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
setIsAdding(false)
|
||||||
|
setConfigInput("")
|
||||||
|
|
||||||
|
// Here you would trigger the actual server connection
|
||||||
|
// and update its status/tools/resources accordingly
|
||||||
|
} catch (e) {
|
||||||
|
// Handle invalid JSON
|
||||||
|
console.error("Invalid server configuration:", e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
@@ -24,14 +134,256 @@ const McpView = ({ onDone }: McpViewProps) => {
|
|||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
padding: "10px 17px 10px 20px",
|
padding: "10px 17px 10px 20px",
|
||||||
}}>
|
}}>
|
||||||
<h3 style={{ color: "var(--vscode-foreground)", margin: 0 }}>MCP</h3>
|
<h3 style={{ color: "var(--vscode-foreground)", margin: 0 }}>MCP Servers</h3>
|
||||||
<VSCodeButton onClick={onDone}>Done</VSCodeButton>
|
<VSCodeButton onClick={onDone}>Done</VSCodeButton>
|
||||||
</div>
|
</div>
|
||||||
<div style={{ padding: "20px", display: "flex", justifyContent: "center" }}>
|
<p style={{ padding: "0 20px", color: "var(--vscode-foreground)", fontSize: "13px" }}>
|
||||||
<VSCodeButton>Add Server</VSCodeButton>
|
MCP (Model Context Protocol) enables AI models to access external tools and data through standardized
|
||||||
|
interfaces. Add MCP servers to extend Claude's capabilities with custom functionality and real-time data
|
||||||
|
access.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
{/* Server List */}
|
||||||
|
<div style={{ flex: 1, overflow: "auto", padding: "0 20px" }}>
|
||||||
|
{servers.map((server) => (
|
||||||
|
<ServerRow key={server.name} server={server} />
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Add Server UI */}
|
||||||
|
<div style={{ padding: "20px" }}>
|
||||||
|
{isAdding ? (
|
||||||
|
<div style={{ display: "flex", flexDirection: "column", gap: "10px" }}>
|
||||||
|
<VSCodeTextArea
|
||||||
|
rows={4}
|
||||||
|
placeholder='{"mcpServers": {"server-name": {"command": "...", "args": [...]}}}'
|
||||||
|
value={configInput}
|
||||||
|
onChange={(e) => setConfigInput((e.target as HTMLTextAreaElement).value)}
|
||||||
|
/>
|
||||||
|
<div style={{ display: "flex", gap: "10px" }}>
|
||||||
|
<VSCodeButton style={{ flex: 1 }} onClick={handleAddServer}>
|
||||||
|
Add Server
|
||||||
|
</VSCodeButton>
|
||||||
|
<VSCodeButton style={{ flex: 1 }} appearance="secondary" onClick={() => setIsAdding(false)}>
|
||||||
|
Cancel
|
||||||
|
</VSCodeButton>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<VSCodeButton style={{ width: "100%" }} onClick={() => setIsAdding(true)}>
|
||||||
|
<span className="codicon codicon-add" style={{ marginRight: "6px" }}></span>
|
||||||
|
Add MCP Server
|
||||||
|
</VSCodeButton>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Server Row Component
|
||||||
|
const ServerRow = ({ server }: { server: McpServer }) => {
|
||||||
|
const [isExpanded, setIsExpanded] = useState(false)
|
||||||
|
const [isEditing, setIsEditing] = useState(false)
|
||||||
|
const [editConfig, setEditConfig] = useState(server.config)
|
||||||
|
|
||||||
|
const getStatusColor = () => {
|
||||||
|
switch (server.status) {
|
||||||
|
case "connected":
|
||||||
|
return "var(--vscode-testing-iconPassed)"
|
||||||
|
case "connecting":
|
||||||
|
return "var(--vscode-charts-yellow)"
|
||||||
|
case "disconnected":
|
||||||
|
return "var(--vscode-testing-iconFailed)"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleSaveConfig = () => {
|
||||||
|
try {
|
||||||
|
JSON.parse(editConfig) // Validate JSON
|
||||||
|
// Here you would update the server config
|
||||||
|
setIsEditing(false)
|
||||||
|
} catch (e) {
|
||||||
|
console.error("Invalid JSON config:", e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Don't allow expansion if server has error
|
||||||
|
const handleRowClick = () => {
|
||||||
|
if (!server.error) {
|
||||||
|
setIsExpanded(!isExpanded)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div style={{ marginBottom: "10px" }}>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
padding: "8px",
|
||||||
|
background: "var(--vscode-list-hoverBackground)",
|
||||||
|
cursor: server.error ? "default" : "pointer",
|
||||||
|
borderRadius: isExpanded || server.error ? "4px 4px 0 0" : "4px",
|
||||||
|
}}
|
||||||
|
onClick={handleRowClick}>
|
||||||
|
{!server.error && (
|
||||||
|
<span
|
||||||
|
className={`codicon codicon-chevron-${isExpanded ? "down" : "right"}`}
|
||||||
|
style={{ marginRight: "8px" }}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
<span style={{ flex: 1 }}>{server.name}</span>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
width: "8px",
|
||||||
|
height: "8px",
|
||||||
|
borderRadius: "50%",
|
||||||
|
background: getStatusColor(),
|
||||||
|
marginLeft: "8px",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{server.error ? (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
padding: "8px",
|
||||||
|
fontSize: "13px",
|
||||||
|
color: "var(--vscode-testing-iconFailed)",
|
||||||
|
background: "var(--vscode-list-hoverBackground)",
|
||||||
|
borderRadius: "0 0 4px 4px",
|
||||||
|
}}>
|
||||||
|
{server.error}
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
isExpanded && (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
background: "var(--vscode-list-hoverBackground)",
|
||||||
|
padding: "0 12px 12px 12px",
|
||||||
|
fontSize: "13px",
|
||||||
|
borderRadius: "0 0 4px 4px",
|
||||||
|
}}>
|
||||||
|
<VSCodePanels>
|
||||||
|
<VSCodePanelTab id="tools">Tools ({server.tools?.length || 0})</VSCodePanelTab>
|
||||||
|
<VSCodePanelTab id="resources">Resources ({server.resources?.length || 0})</VSCodePanelTab>
|
||||||
|
|
||||||
|
<VSCodePanelView id="tools-view">
|
||||||
|
{server.tools && server.tools.length > 0 ? (
|
||||||
|
<div style={{ display: "flex", flexDirection: "column", gap: "3px" }}>
|
||||||
|
{server.tools.map((tool) => (
|
||||||
|
<div
|
||||||
|
key={tool.name}
|
||||||
|
style={{
|
||||||
|
padding: "8px 0",
|
||||||
|
}}>
|
||||||
|
<div style={{ display: "flex" }}>
|
||||||
|
<span
|
||||||
|
className="codicon codicon-symbol-method"
|
||||||
|
style={{ marginRight: "6px" }}></span>
|
||||||
|
<span style={{ fontWeight: 500 }}>{tool.name}</span>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
marginLeft: "0px",
|
||||||
|
marginTop: "4px",
|
||||||
|
opacity: 0.8,
|
||||||
|
fontSize: "12px",
|
||||||
|
}}>
|
||||||
|
{tool.description}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div style={{ padding: "10px 0", color: "var(--vscode-descriptionForeground)" }}>
|
||||||
|
No tools found
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</VSCodePanelView>
|
||||||
|
|
||||||
|
{/* Resources Panel View */}
|
||||||
|
<VSCodePanelView id="resources-view">
|
||||||
|
{server.resources && server.resources.length > 0 ? (
|
||||||
|
<div style={{ display: "flex", flexDirection: "column", gap: "3px" }}>
|
||||||
|
{server.resources.map((resource) => (
|
||||||
|
<div
|
||||||
|
key={resource.uri}
|
||||||
|
style={{
|
||||||
|
padding: "8px 0",
|
||||||
|
}}>
|
||||||
|
<div style={{ display: "flex" }}>
|
||||||
|
<span
|
||||||
|
className="codicon codicon-symbol-file"
|
||||||
|
style={{ marginRight: "6px" }}></span>
|
||||||
|
<span style={{ fontWeight: 500 }}>{resource.name}</span>
|
||||||
|
</div>
|
||||||
|
<div style={{ marginTop: "6px", fontSize: "12px" }}>
|
||||||
|
<code
|
||||||
|
style={{
|
||||||
|
color: "var(--vscode-textPreformat-foreground)",
|
||||||
|
background: "var(--vscode-textPreformat-background)",
|
||||||
|
padding: "2px 4px",
|
||||||
|
borderRadius: "3px",
|
||||||
|
}}>
|
||||||
|
{resource.uri}
|
||||||
|
</code>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div style={{ padding: "10px 0", color: "var(--vscode-descriptionForeground)" }}>
|
||||||
|
No resources found
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</VSCodePanelView>
|
||||||
|
</VSCodePanels>
|
||||||
|
|
||||||
|
{/* Edit/Remove Buttons */}
|
||||||
|
<div style={{ display: "flex", flexDirection: "column", gap: "8px", marginTop: "0px" }}>
|
||||||
|
{isEditing ? (
|
||||||
|
<>
|
||||||
|
<VSCodeTextArea
|
||||||
|
value={editConfig}
|
||||||
|
onChange={(e) => setEditConfig((e.target as HTMLTextAreaElement).value)}
|
||||||
|
style={{ width: "100%" }}
|
||||||
|
/>
|
||||||
|
<div style={{ display: "flex", gap: "8px" }}>
|
||||||
|
<VSCodeButton onClick={handleSaveConfig} style={{ flex: 1 }}>
|
||||||
|
Save
|
||||||
|
</VSCodeButton>
|
||||||
|
<VSCodeButton
|
||||||
|
appearance="secondary"
|
||||||
|
onClick={() => setIsEditing(false)}
|
||||||
|
style={{ flex: 1 }}>
|
||||||
|
Cancel
|
||||||
|
</VSCodeButton>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<div style={{ display: "flex", gap: "8px" }}>
|
||||||
|
<VSCodeButton
|
||||||
|
appearance="secondary"
|
||||||
|
onClick={() => setIsEditing(true)}
|
||||||
|
style={{ flex: 1 }}>
|
||||||
|
Edit
|
||||||
|
</VSCodeButton>
|
||||||
|
<VSCodeButton
|
||||||
|
appearance="secondary"
|
||||||
|
style={{
|
||||||
|
flex: 1,
|
||||||
|
}}>
|
||||||
|
Remove
|
||||||
|
</VSCodeButton>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
export default McpView
|
export default McpView
|
||||||
|
|||||||
Reference in New Issue
Block a user