mirror of
https://github.com/aljazceru/opencode.git
synced 2025-12-22 10:14:22 +01:00
add optional timeout field to mcp config to allow users to use responding servers (#3558)
Co-authored-by: Matt Gillard <matt-github@gillard.biz> Co-authored-by: opencode-agent[bot] <opencode-agent[bot]@users.noreply.github.com> Co-authored-by: rekram1-node <rekram1-node@users.noreply.github.com>
This commit is contained in:
@@ -12,7 +12,11 @@ import { NamedError } from "../util/error"
|
|||||||
import matter from "gray-matter"
|
import matter from "gray-matter"
|
||||||
import { Flag } from "../flag/flag"
|
import { Flag } from "../flag/flag"
|
||||||
import { Auth } from "../auth"
|
import { Auth } from "../auth"
|
||||||
import { type ParseError as JsoncParseError, parse as parseJsonc, printParseErrorCode } from "jsonc-parser"
|
import {
|
||||||
|
type ParseError as JsoncParseError,
|
||||||
|
parse as parseJsonc,
|
||||||
|
printParseErrorCode,
|
||||||
|
} from "jsonc-parser"
|
||||||
import { Instance } from "../project/instance"
|
import { Instance } from "../project/instance"
|
||||||
import { LSPServer } from "../lsp/server"
|
import { LSPServer } from "../lsp/server"
|
||||||
import { BunProc } from "@/bun"
|
import { BunProc } from "@/bun"
|
||||||
@@ -46,7 +50,10 @@ export namespace Config {
|
|||||||
if (value.type === "wellknown") {
|
if (value.type === "wellknown") {
|
||||||
process.env[value.key] = value.token
|
process.env[value.key] = value.token
|
||||||
const wellknown = await fetch(`${key}/.well-known/opencode`).then((x) => x.json())
|
const wellknown = await fetch(`${key}/.well-known/opencode`).then((x) => x.json())
|
||||||
result = mergeDeep(result, await load(JSON.stringify(wellknown.config ?? {}), process.cwd()))
|
result = mergeDeep(
|
||||||
|
result,
|
||||||
|
await load(JSON.stringify(wellknown.config ?? {}), process.cwd()),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,7 +64,11 @@ export namespace Config {
|
|||||||
const directories = [
|
const directories = [
|
||||||
Global.Path.config,
|
Global.Path.config,
|
||||||
...(await Array.fromAsync(
|
...(await Array.fromAsync(
|
||||||
Filesystem.up({ targets: [".opencode"], start: Instance.directory, stop: Instance.worktree }),
|
Filesystem.up({
|
||||||
|
targets: [".opencode"],
|
||||||
|
start: Instance.directory,
|
||||||
|
stop: Instance.worktree,
|
||||||
|
}),
|
||||||
)),
|
)),
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -153,10 +164,18 @@ export namespace Config {
|
|||||||
|
|
||||||
const gitignore = path.join(dir, ".gitignore")
|
const gitignore = path.join(dir, ".gitignore")
|
||||||
const hasGitIgnore = await Bun.file(gitignore).exists()
|
const hasGitIgnore = await Bun.file(gitignore).exists()
|
||||||
if (!hasGitIgnore) await Bun.write(gitignore, ["node_modules", "package.json", "bun.lock", ".gitignore"].join("\n"))
|
if (!hasGitIgnore)
|
||||||
|
await Bun.write(
|
||||||
|
gitignore,
|
||||||
|
["node_modules", "package.json", "bun.lock", ".gitignore"].join("\n"),
|
||||||
|
)
|
||||||
|
|
||||||
await BunProc.run(
|
await BunProc.run(
|
||||||
["add", "@opencode-ai/plugin@" + (Installation.isLocal() ? "latest" : Installation.VERSION), "--exact"],
|
[
|
||||||
|
"add",
|
||||||
|
"@opencode-ai/plugin@" + (Installation.isLocal() ? "latest" : Installation.VERSION),
|
||||||
|
"--exact",
|
||||||
|
],
|
||||||
{
|
{
|
||||||
cwd: dir,
|
cwd: dir,
|
||||||
},
|
},
|
||||||
@@ -166,7 +185,12 @@ export namespace Config {
|
|||||||
const COMMAND_GLOB = new Bun.Glob("command/**/*.md")
|
const COMMAND_GLOB = new Bun.Glob("command/**/*.md")
|
||||||
async function loadCommand(dir: string) {
|
async function loadCommand(dir: string) {
|
||||||
const result: Record<string, Command> = {}
|
const result: Record<string, Command> = {}
|
||||||
for await (const item of COMMAND_GLOB.scan({ absolute: true, followSymlinks: true, dot: true, cwd: dir })) {
|
for await (const item of COMMAND_GLOB.scan({
|
||||||
|
absolute: true,
|
||||||
|
followSymlinks: true,
|
||||||
|
dot: true,
|
||||||
|
cwd: dir,
|
||||||
|
})) {
|
||||||
const content = await Bun.file(item).text()
|
const content = await Bun.file(item).text()
|
||||||
const md = matter(content)
|
const md = matter(content)
|
||||||
if (!md.data) continue
|
if (!md.data) continue
|
||||||
@@ -201,7 +225,12 @@ export namespace Config {
|
|||||||
async function loadAgent(dir: string) {
|
async function loadAgent(dir: string) {
|
||||||
const result: Record<string, Agent> = {}
|
const result: Record<string, Agent> = {}
|
||||||
|
|
||||||
for await (const item of AGENT_GLOB.scan({ absolute: true, followSymlinks: true, dot: true, cwd: dir })) {
|
for await (const item of AGENT_GLOB.scan({
|
||||||
|
absolute: true,
|
||||||
|
followSymlinks: true,
|
||||||
|
dot: true,
|
||||||
|
cwd: dir,
|
||||||
|
})) {
|
||||||
const content = await Bun.file(item).text()
|
const content = await Bun.file(item).text()
|
||||||
const md = matter(content)
|
const md = matter(content)
|
||||||
if (!md.data) continue
|
if (!md.data) continue
|
||||||
@@ -239,7 +268,12 @@ export namespace Config {
|
|||||||
const MODE_GLOB = new Bun.Glob("mode/*.md")
|
const MODE_GLOB = new Bun.Glob("mode/*.md")
|
||||||
async function loadMode(dir: string) {
|
async function loadMode(dir: string) {
|
||||||
const result: Record<string, Agent> = {}
|
const result: Record<string, Agent> = {}
|
||||||
for await (const item of MODE_GLOB.scan({ absolute: true, followSymlinks: true, dot: true, cwd: dir })) {
|
for await (const item of MODE_GLOB.scan({
|
||||||
|
absolute: true,
|
||||||
|
followSymlinks: true,
|
||||||
|
dot: true,
|
||||||
|
cwd: dir,
|
||||||
|
})) {
|
||||||
const content = await Bun.file(item).text()
|
const content = await Bun.file(item).text()
|
||||||
const md = matter(content)
|
const md = matter(content)
|
||||||
if (!md.data) continue
|
if (!md.data) continue
|
||||||
@@ -265,7 +299,12 @@ export namespace Config {
|
|||||||
async function loadPlugin(dir: string) {
|
async function loadPlugin(dir: string) {
|
||||||
const plugins: string[] = []
|
const plugins: string[] = []
|
||||||
|
|
||||||
for await (const item of PLUGIN_GLOB.scan({ absolute: true, followSymlinks: true, dot: true, cwd: dir })) {
|
for await (const item of PLUGIN_GLOB.scan({
|
||||||
|
absolute: true,
|
||||||
|
followSymlinks: true,
|
||||||
|
dot: true,
|
||||||
|
cwd: dir,
|
||||||
|
})) {
|
||||||
plugins.push("file://" + item)
|
plugins.push("file://" + item)
|
||||||
}
|
}
|
||||||
return plugins
|
return plugins
|
||||||
@@ -280,6 +319,14 @@ export namespace Config {
|
|||||||
.optional()
|
.optional()
|
||||||
.describe("Environment variables to set when running the MCP server"),
|
.describe("Environment variables to set when running the MCP server"),
|
||||||
enabled: z.boolean().optional().describe("Enable or disable the MCP server on startup"),
|
enabled: z.boolean().optional().describe("Enable or disable the MCP server on startup"),
|
||||||
|
timeout: z
|
||||||
|
.number()
|
||||||
|
.int()
|
||||||
|
.positive()
|
||||||
|
.optional()
|
||||||
|
.describe(
|
||||||
|
"Timeout in ms for fetching tools from the MCP server. Defaults to 5000 (5 seconds) if not specified.",
|
||||||
|
),
|
||||||
})
|
})
|
||||||
.strict()
|
.strict()
|
||||||
.meta({
|
.meta({
|
||||||
@@ -291,7 +338,18 @@ export namespace Config {
|
|||||||
type: z.literal("remote").describe("Type of MCP server connection"),
|
type: z.literal("remote").describe("Type of MCP server connection"),
|
||||||
url: z.string().describe("URL of the remote MCP server"),
|
url: z.string().describe("URL of the remote MCP server"),
|
||||||
enabled: z.boolean().optional().describe("Enable or disable the MCP server on startup"),
|
enabled: z.boolean().optional().describe("Enable or disable the MCP server on startup"),
|
||||||
headers: z.record(z.string(), z.string()).optional().describe("Headers to send with the request"),
|
headers: z
|
||||||
|
.record(z.string(), z.string())
|
||||||
|
.optional()
|
||||||
|
.describe("Headers to send with the request"),
|
||||||
|
timeout: z
|
||||||
|
.number()
|
||||||
|
.int()
|
||||||
|
.positive()
|
||||||
|
.optional()
|
||||||
|
.describe(
|
||||||
|
"Timeout in ms for fetching tools from the MCP server. Defaults to 5000 (5 seconds) if not specified.",
|
||||||
|
),
|
||||||
})
|
})
|
||||||
.strict()
|
.strict()
|
||||||
.meta({
|
.meta({
|
||||||
@@ -339,72 +397,148 @@ export namespace Config {
|
|||||||
|
|
||||||
export const Keybinds = z
|
export const Keybinds = z
|
||||||
.object({
|
.object({
|
||||||
leader: z.string().optional().default("ctrl+x").describe("Leader key for keybind combinations"),
|
leader: z
|
||||||
|
.string()
|
||||||
|
.optional()
|
||||||
|
.default("ctrl+x")
|
||||||
|
.describe("Leader key for keybind combinations"),
|
||||||
app_help: z.string().optional().default("<leader>h").describe("Show help dialog"),
|
app_help: z.string().optional().default("<leader>h").describe("Show help dialog"),
|
||||||
app_exit: z.string().optional().default("ctrl+c,<leader>q").describe("Exit the application"),
|
app_exit: z.string().optional().default("ctrl+c,<leader>q").describe("Exit the application"),
|
||||||
editor_open: z.string().optional().default("<leader>e").describe("Open external editor"),
|
editor_open: z.string().optional().default("<leader>e").describe("Open external editor"),
|
||||||
theme_list: z.string().optional().default("<leader>t").describe("List available themes"),
|
theme_list: z.string().optional().default("<leader>t").describe("List available themes"),
|
||||||
project_init: z.string().optional().default("<leader>i").describe("Create/update AGENTS.md"),
|
project_init: z.string().optional().default("<leader>i").describe("Create/update AGENTS.md"),
|
||||||
tool_details: z.string().optional().default("<leader>d").describe("Toggle tool details"),
|
tool_details: z.string().optional().default("<leader>d").describe("Toggle tool details"),
|
||||||
thinking_blocks: z.string().optional().default("<leader>b").describe("Toggle thinking blocks"),
|
thinking_blocks: z
|
||||||
session_export: z.string().optional().default("<leader>x").describe("Export session to editor"),
|
.string()
|
||||||
|
.optional()
|
||||||
|
.default("<leader>b")
|
||||||
|
.describe("Toggle thinking blocks"),
|
||||||
|
session_export: z
|
||||||
|
.string()
|
||||||
|
.optional()
|
||||||
|
.default("<leader>x")
|
||||||
|
.describe("Export session to editor"),
|
||||||
session_new: z.string().optional().default("<leader>n").describe("Create a new session"),
|
session_new: z.string().optional().default("<leader>n").describe("Create a new session"),
|
||||||
session_list: z.string().optional().default("<leader>l").describe("List all sessions"),
|
session_list: z.string().optional().default("<leader>l").describe("List all sessions"),
|
||||||
session_timeline: z.string().optional().default("<leader>g").describe("Show session timeline"),
|
session_timeline: z
|
||||||
|
.string()
|
||||||
|
.optional()
|
||||||
|
.default("<leader>g")
|
||||||
|
.describe("Show session timeline"),
|
||||||
session_share: z.string().optional().default("<leader>s").describe("Share current session"),
|
session_share: z.string().optional().default("<leader>s").describe("Share current session"),
|
||||||
session_unshare: z.string().optional().default("none").describe("Unshare current session"),
|
session_unshare: z.string().optional().default("none").describe("Unshare current session"),
|
||||||
session_interrupt: z.string().optional().default("esc").describe("Interrupt current session"),
|
session_interrupt: z.string().optional().default("esc").describe("Interrupt current session"),
|
||||||
session_compact: z.string().optional().default("<leader>c").describe("Compact the session"),
|
session_compact: z.string().optional().default("<leader>c").describe("Compact the session"),
|
||||||
session_child_cycle: z.string().optional().default("ctrl+right").describe("Cycle to next child session"),
|
session_child_cycle: z
|
||||||
|
.string()
|
||||||
|
.optional()
|
||||||
|
.default("ctrl+right")
|
||||||
|
.describe("Cycle to next child session"),
|
||||||
session_child_cycle_reverse: z
|
session_child_cycle_reverse: z
|
||||||
.string()
|
.string()
|
||||||
.optional()
|
.optional()
|
||||||
.default("ctrl+left")
|
.default("ctrl+left")
|
||||||
.describe("Cycle to previous child session"),
|
.describe("Cycle to previous child session"),
|
||||||
messages_page_up: z.string().optional().default("pgup").describe("Scroll messages up by one page"),
|
messages_page_up: z
|
||||||
messages_page_down: z.string().optional().default("pgdown").describe("Scroll messages down by one page"),
|
.string()
|
||||||
messages_half_page_up: z.string().optional().default("ctrl+alt+u").describe("Scroll messages up by half page"),
|
.optional()
|
||||||
|
.default("pgup")
|
||||||
|
.describe("Scroll messages up by one page"),
|
||||||
|
messages_page_down: z
|
||||||
|
.string()
|
||||||
|
.optional()
|
||||||
|
.default("pgdown")
|
||||||
|
.describe("Scroll messages down by one page"),
|
||||||
|
messages_half_page_up: z
|
||||||
|
.string()
|
||||||
|
.optional()
|
||||||
|
.default("ctrl+alt+u")
|
||||||
|
.describe("Scroll messages up by half page"),
|
||||||
messages_half_page_down: z
|
messages_half_page_down: z
|
||||||
.string()
|
.string()
|
||||||
.optional()
|
.optional()
|
||||||
.default("ctrl+alt+d")
|
.default("ctrl+alt+d")
|
||||||
.describe("Scroll messages down by half page"),
|
.describe("Scroll messages down by half page"),
|
||||||
messages_first: z.string().optional().default("ctrl+g").describe("Navigate to first message"),
|
messages_first: z.string().optional().default("ctrl+g").describe("Navigate to first message"),
|
||||||
messages_last: z.string().optional().default("ctrl+alt+g").describe("Navigate to last message"),
|
messages_last: z
|
||||||
|
.string()
|
||||||
|
.optional()
|
||||||
|
.default("ctrl+alt+g")
|
||||||
|
.describe("Navigate to last message"),
|
||||||
messages_copy: z.string().optional().default("<leader>y").describe("Copy message"),
|
messages_copy: z.string().optional().default("<leader>y").describe("Copy message"),
|
||||||
messages_undo: z.string().optional().default("<leader>u").describe("Undo message"),
|
messages_undo: z.string().optional().default("<leader>u").describe("Undo message"),
|
||||||
messages_redo: z.string().optional().default("<leader>r").describe("Redo message"),
|
messages_redo: z.string().optional().default("<leader>r").describe("Redo message"),
|
||||||
model_list: z.string().optional().default("<leader>m").describe("List available models"),
|
model_list: z.string().optional().default("<leader>m").describe("List available models"),
|
||||||
model_cycle_recent: z.string().optional().default("f2").describe("Next recent model"),
|
model_cycle_recent: z.string().optional().default("f2").describe("Next recent model"),
|
||||||
model_cycle_recent_reverse: z.string().optional().default("shift+f2").describe("Previous recent model"),
|
model_cycle_recent_reverse: z
|
||||||
|
.string()
|
||||||
|
.optional()
|
||||||
|
.default("shift+f2")
|
||||||
|
.describe("Previous recent model"),
|
||||||
agent_list: z.string().optional().default("<leader>a").describe("List agents"),
|
agent_list: z.string().optional().default("<leader>a").describe("List agents"),
|
||||||
agent_cycle: z.string().optional().default("tab").describe("Next agent"),
|
agent_cycle: z.string().optional().default("tab").describe("Next agent"),
|
||||||
agent_cycle_reverse: z.string().optional().default("shift+tab").describe("Previous agent"),
|
agent_cycle_reverse: z.string().optional().default("shift+tab").describe("Previous agent"),
|
||||||
input_clear: z.string().optional().default("ctrl+c").describe("Clear input field"),
|
input_clear: z.string().optional().default("ctrl+c").describe("Clear input field"),
|
||||||
input_paste: z.string().optional().default("ctrl+v").describe("Paste from clipboard"),
|
input_paste: z.string().optional().default("ctrl+v").describe("Paste from clipboard"),
|
||||||
input_submit: z.string().optional().default("enter").describe("Submit input"),
|
input_submit: z.string().optional().default("enter").describe("Submit input"),
|
||||||
input_newline: z.string().optional().default("shift+enter,ctrl+j").describe("Insert newline in input"),
|
input_newline: z
|
||||||
|
.string()
|
||||||
|
.optional()
|
||||||
|
.default("shift+enter,ctrl+j")
|
||||||
|
.describe("Insert newline in input"),
|
||||||
// Deprecated commands
|
// Deprecated commands
|
||||||
switch_mode: z.string().optional().default("none").describe("@deprecated use agent_cycle. Next mode"),
|
switch_mode: z
|
||||||
|
.string()
|
||||||
|
.optional()
|
||||||
|
.default("none")
|
||||||
|
.describe("@deprecated use agent_cycle. Next mode"),
|
||||||
switch_mode_reverse: z
|
switch_mode_reverse: z
|
||||||
.string()
|
.string()
|
||||||
.optional()
|
.optional()
|
||||||
.default("none")
|
.default("none")
|
||||||
.describe("@deprecated use agent_cycle_reverse. Previous mode"),
|
.describe("@deprecated use agent_cycle_reverse. Previous mode"),
|
||||||
switch_agent: z.string().optional().default("tab").describe("@deprecated use agent_cycle. Next agent"),
|
switch_agent: z
|
||||||
|
.string()
|
||||||
|
.optional()
|
||||||
|
.default("tab")
|
||||||
|
.describe("@deprecated use agent_cycle. Next agent"),
|
||||||
switch_agent_reverse: z
|
switch_agent_reverse: z
|
||||||
.string()
|
.string()
|
||||||
.optional()
|
.optional()
|
||||||
.default("shift+tab")
|
.default("shift+tab")
|
||||||
.describe("@deprecated use agent_cycle_reverse. Previous agent"),
|
.describe("@deprecated use agent_cycle_reverse. Previous agent"),
|
||||||
file_list: z.string().optional().default("none").describe("@deprecated Currently not available. List files"),
|
file_list: z
|
||||||
|
.string()
|
||||||
|
.optional()
|
||||||
|
.default("none")
|
||||||
|
.describe("@deprecated Currently not available. List files"),
|
||||||
file_close: z.string().optional().default("none").describe("@deprecated Close file"),
|
file_close: z.string().optional().default("none").describe("@deprecated Close file"),
|
||||||
file_search: z.string().optional().default("none").describe("@deprecated Search file"),
|
file_search: z.string().optional().default("none").describe("@deprecated Search file"),
|
||||||
file_diff_toggle: z.string().optional().default("none").describe("@deprecated Split/unified diff"),
|
file_diff_toggle: z
|
||||||
messages_previous: z.string().optional().default("none").describe("@deprecated Navigate to previous message"),
|
.string()
|
||||||
messages_next: z.string().optional().default("none").describe("@deprecated Navigate to next message"),
|
.optional()
|
||||||
messages_layout_toggle: z.string().optional().default("none").describe("@deprecated Toggle layout"),
|
.default("none")
|
||||||
messages_revert: z.string().optional().default("none").describe("@deprecated use messages_undo. Revert message"),
|
.describe("@deprecated Split/unified diff"),
|
||||||
|
messages_previous: z
|
||||||
|
.string()
|
||||||
|
.optional()
|
||||||
|
.default("none")
|
||||||
|
.describe("@deprecated Navigate to previous message"),
|
||||||
|
messages_next: z
|
||||||
|
.string()
|
||||||
|
.optional()
|
||||||
|
.default("none")
|
||||||
|
.describe("@deprecated Navigate to next message"),
|
||||||
|
messages_layout_toggle: z
|
||||||
|
.string()
|
||||||
|
.optional()
|
||||||
|
.default("none")
|
||||||
|
.describe("@deprecated Toggle layout"),
|
||||||
|
messages_revert: z
|
||||||
|
.string()
|
||||||
|
.optional()
|
||||||
|
.default("none")
|
||||||
|
.describe("@deprecated use messages_undo. Revert message"),
|
||||||
})
|
})
|
||||||
.strict()
|
.strict()
|
||||||
.meta({
|
.meta({
|
||||||
@@ -446,13 +580,23 @@ export namespace Config {
|
|||||||
autoshare: z
|
autoshare: z
|
||||||
.boolean()
|
.boolean()
|
||||||
.optional()
|
.optional()
|
||||||
.describe("@deprecated Use 'share' field instead. Share newly created sessions automatically"),
|
.describe(
|
||||||
|
"@deprecated Use 'share' field instead. Share newly created sessions automatically",
|
||||||
|
),
|
||||||
autoupdate: z.boolean().optional().describe("Automatically update to the latest version"),
|
autoupdate: z.boolean().optional().describe("Automatically update to the latest version"),
|
||||||
disabled_providers: z.array(z.string()).optional().describe("Disable providers that are loaded automatically"),
|
disabled_providers: z
|
||||||
model: z.string().describe("Model to use in the format of provider/model, eg anthropic/claude-2").optional(),
|
.array(z.string())
|
||||||
|
.optional()
|
||||||
|
.describe("Disable providers that are loaded automatically"),
|
||||||
|
model: z
|
||||||
|
.string()
|
||||||
|
.describe("Model to use in the format of provider/model, eg anthropic/claude-2")
|
||||||
|
.optional(),
|
||||||
small_model: z
|
small_model: z
|
||||||
.string()
|
.string()
|
||||||
.describe("Small model to use for tasks like title generation in the format of provider/model")
|
.describe(
|
||||||
|
"Small model to use for tasks like title generation in the format of provider/model",
|
||||||
|
)
|
||||||
.optional(),
|
.optional(),
|
||||||
username: z
|
username: z
|
||||||
.string()
|
.string()
|
||||||
@@ -508,7 +652,10 @@ export namespace Config {
|
|||||||
)
|
)
|
||||||
.optional()
|
.optional()
|
||||||
.describe("Custom provider configurations and model overrides"),
|
.describe("Custom provider configurations and model overrides"),
|
||||||
mcp: z.record(z.string(), Mcp).optional().describe("MCP (Model Context Protocol) server configurations"),
|
mcp: z
|
||||||
|
.record(z.string(), Mcp)
|
||||||
|
.optional()
|
||||||
|
.describe("MCP (Model Context Protocol) server configurations"),
|
||||||
formatter: z
|
formatter: z
|
||||||
.record(
|
.record(
|
||||||
z.string(),
|
z.string(),
|
||||||
@@ -552,7 +699,10 @@ export namespace Config {
|
|||||||
error: "For custom LSP servers, 'extensions' array is required.",
|
error: "For custom LSP servers, 'extensions' array is required.",
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
instructions: z.array(z.string()).optional().describe("Additional instruction files or patterns to include"),
|
instructions: z
|
||||||
|
.array(z.string())
|
||||||
|
.optional()
|
||||||
|
.describe("Additional instruction files or patterns to include"),
|
||||||
layout: Layout.optional().describe("@deprecated Always uses stretch layout."),
|
layout: Layout.optional().describe("@deprecated Always uses stretch layout."),
|
||||||
permission: z
|
permission: z
|
||||||
.object({
|
.object({
|
||||||
@@ -586,7 +736,10 @@ export namespace Config {
|
|||||||
.optional(),
|
.optional(),
|
||||||
})
|
})
|
||||||
.optional(),
|
.optional(),
|
||||||
chatMaxRetries: z.number().optional().describe("Number of retries for chat completions on failure"),
|
chatMaxRetries: z
|
||||||
|
.number()
|
||||||
|
.optional()
|
||||||
|
.describe("Number of retries for chat completions on failure"),
|
||||||
disable_paste_summary: z.boolean().optional(),
|
disable_paste_summary: z.boolean().optional(),
|
||||||
})
|
})
|
||||||
.optional(),
|
.optional(),
|
||||||
@@ -616,7 +769,10 @@ export namespace Config {
|
|||||||
if (provider && model) result.model = `${provider}/${model}`
|
if (provider && model) result.model = `${provider}/${model}`
|
||||||
result["$schema"] = "https://opencode.ai/config.json"
|
result["$schema"] = "https://opencode.ai/config.json"
|
||||||
result = mergeDeep(result, rest)
|
result = mergeDeep(result, rest)
|
||||||
await Bun.write(path.join(Global.Path.config, "config.json"), JSON.stringify(result, null, 2))
|
await Bun.write(
|
||||||
|
path.join(Global.Path.config, "config.json"),
|
||||||
|
JSON.stringify(result, null, 2),
|
||||||
|
)
|
||||||
await fs.unlink(path.join(Global.Path.config, "config"))
|
await fs.unlink(path.join(Global.Path.config, "config"))
|
||||||
})
|
})
|
||||||
.catch(() => {})
|
.catch(() => {})
|
||||||
@@ -655,7 +811,9 @@ export namespace Config {
|
|||||||
if (filePath.startsWith("~/")) {
|
if (filePath.startsWith("~/")) {
|
||||||
filePath = path.join(os.homedir(), filePath.slice(2))
|
filePath = path.join(os.homedir(), filePath.slice(2))
|
||||||
}
|
}
|
||||||
const resolvedPath = path.isAbsolute(filePath) ? filePath : path.resolve(configDir, filePath)
|
const resolvedPath = path.isAbsolute(filePath)
|
||||||
|
? filePath
|
||||||
|
: path.resolve(configDir, filePath)
|
||||||
const fileContent = (
|
const fileContent = (
|
||||||
await Bun.file(resolvedPath)
|
await Bun.file(resolvedPath)
|
||||||
.text()
|
.text()
|
||||||
|
|||||||
@@ -167,7 +167,7 @@ export namespace MCP {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = await withTimeout(mcpClient.tools(), 5000).catch(() => {})
|
const result = await withTimeout(mcpClient.tools(), mcp.timeout ?? 5000).catch(() => { })
|
||||||
if (!result) {
|
if (!result) {
|
||||||
log.warn("mcp client verification failed, dropping client", { name })
|
log.warn("mcp client verification failed, dropping client", { name })
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -45,12 +45,12 @@ with a unique name. You can refer to that MCP by name when prompting the LLM.
|
|||||||
"mcp": {
|
"mcp": {
|
||||||
"name-of-mcp-server": {
|
"name-of-mcp-server": {
|
||||||
// ...
|
// ...
|
||||||
"enabled": true
|
"enabled": true,
|
||||||
},
|
},
|
||||||
"name-of-other-mcp-server": {
|
"name-of-other-mcp-server": {
|
||||||
// ...
|
// ...
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -72,10 +72,10 @@ Add local MCP servers using `type` to `"local"` within the MCP object.
|
|||||||
"command": ["npx", "-y", "my-mcp-command"],
|
"command": ["npx", "-y", "my-mcp-command"],
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"environment": {
|
"environment": {
|
||||||
"MY_ENV_VAR": "my_env_var_value"
|
"MY_ENV_VAR": "my_env_var_value",
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -91,8 +91,8 @@ For example, here's how I can add the test
|
|||||||
"mcp_everything": {
|
"mcp_everything": {
|
||||||
"type": "local",
|
"type": "local",
|
||||||
"command": ["npx", "-y", "@modelcontextprotocol/server-everything"],
|
"command": ["npx", "-y", "@modelcontextprotocol/server-everything"],
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -107,11 +107,12 @@ use the mcp_everything tool to add the number 3 and 4
|
|||||||
Here are all the options for configuring a local MCP server.
|
Here are all the options for configuring a local MCP server.
|
||||||
|
|
||||||
| Option | Type | Required | Description |
|
| Option | Type | Required | Description |
|
||||||
| ------------- | ------- | -------- | ----------------------------------------------------- |
|
| ------------- | ------- | -------- | ----------------------------------------------------------------------------------- |
|
||||||
| `type` | String | Y | Type of MCP server connection, must be `"local"`. |
|
| `type` | String | Y | Type of MCP server connection, must be `"local"`. |
|
||||||
| `command` | Array | Y | Command and arguments to run the MCP server. |
|
| `command` | Array | Y | Command and arguments to run the MCP server. |
|
||||||
| `environment` | Object | | Environment variables to set when running the server. |
|
| `environment` | Object | | Environment variables to set when running the server. |
|
||||||
| `enabled` | Boolean | | Enable or disable the MCP server on startup. |
|
| `enabled` | Boolean | | Enable or disable the MCP server on startup. |
|
||||||
|
| `timeout` | Number | | Timeout in ms for fetching tools from the MCP server. Defaults to 5000 (5 seconds). |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -140,11 +141,12 @@ Here the `url` is the URL of the remote MCP server and with the `headers` option
|
|||||||
#### Options
|
#### Options
|
||||||
|
|
||||||
| Option | Type | Required | Description |
|
| Option | Type | Required | Description |
|
||||||
| --------- | ------- | -------- | -------------------------------------------------- |
|
| --------- | ------- | -------- | ----------------------------------------------------------------------------------- |
|
||||||
| `type` | String | Y | Type of MCP server connection, must be `"remote"`. |
|
| `type` | String | Y | Type of MCP server connection, must be `"remote"`. |
|
||||||
| `url` | String | Y | URL of the remote MCP server. |
|
| `url` | String | Y | URL of the remote MCP server. |
|
||||||
| `enabled` | Boolean | | Enable or disable the MCP server on startup. |
|
| `enabled` | Boolean | | Enable or disable the MCP server on startup. |
|
||||||
| `headers` | Object | | Headers to send with the request. |
|
| `headers` | Object | | Headers to send with the request. |
|
||||||
|
| `timeout` | Number | | Timeout in ms for fetching tools from the MCP server. Defaults to 5000 (5 seconds). |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user