feat(mcp): register ast-grep as built-in MCP

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
YeonGyu-Kim
2026-05-18 21:19:24 +09:00
parent 499aff011a
commit ef09880e26
9 changed files with 273 additions and 22 deletions
+1 -1
View File
@@ -38,7 +38,7 @@ export function createConfigHandler(deps: ConfigHandlerDeps) {
});
applyToolConfig({ config, pluginConfig, agentResult });
await applyMcpConfig({ config, pluginConfig, pluginComponents });
await applyMcpConfig({ config, pluginConfig, ctx, pluginComponents });
await applyCommandConfig({ config, pluginConfig, ctx, pluginComponents });
config.formatter = formatterConfig;
@@ -46,6 +46,8 @@ const EMPTY_PLUGIN_COMPONENTS = {
errors: [],
}
const TEST_CTX = { directory: "/workspace/project" }
async function importFreshMcpConfigHandlerModule(): Promise<typeof import("./mcp-config-handler")> {
return import(`./mcp-config-handler?test=${Date.now()}-${Math.random()}`)
}
@@ -69,7 +71,7 @@ describe("applyMcpConfig collision handling", () => {
//#when
const { applyMcpConfig } = await importFreshMcpConfigHandlerModule()
await applyMcpConfig({ config, pluginConfig, pluginComponents: EMPTY_PLUGIN_COMPONENTS })
await applyMcpConfig({ config, ctx: TEST_CTX, pluginConfig, pluginComponents: EMPTY_PLUGIN_COMPONENTS })
//#then
const mergedMcp = config.mcp as Record<string, Record<string, unknown>>
@@ -98,7 +100,7 @@ describe("applyMcpConfig collision handling", () => {
//#when
const { applyMcpConfig } = await importFreshMcpConfigHandlerModule()
await applyMcpConfig({ config, pluginConfig, pluginComponents: EMPTY_PLUGIN_COMPONENTS })
await applyMcpConfig({ config, ctx: TEST_CTX, pluginConfig, pluginComponents: EMPTY_PLUGIN_COMPONENTS })
//#then
const mergedMcp = config.mcp as Record<string, Record<string, unknown>>
@@ -126,7 +128,7 @@ describe("applyMcpConfig collision handling", () => {
//#when
const { applyMcpConfig } = await importFreshMcpConfigHandlerModule()
await applyMcpConfig({ config, pluginConfig, pluginComponents: EMPTY_PLUGIN_COMPONENTS })
await applyMcpConfig({ config, ctx: TEST_CTX, pluginConfig, pluginComponents: EMPTY_PLUGIN_COMPONENTS })
//#then
const mergedMcp = config.mcp as Record<string, Record<string, unknown>>
+20 -3
View File
@@ -42,6 +42,8 @@ const EMPTY_PLUGIN_COMPONENTS = {
errors: [],
}
const TEST_CTX = { directory: "/workspace/project" }
describe("applyMcpConfig", () => {
test("preserves enabled:false from user config after merge with .mcp.json MCPs", async () => {
//#given
@@ -62,7 +64,7 @@ describe("applyMcpConfig", () => {
//#when
const { applyMcpConfig } = await import("./mcp-config-handler")
await applyMcpConfig({ config, pluginConfig, pluginComponents: EMPTY_PLUGIN_COMPONENTS })
await applyMcpConfig({ config, ctx: TEST_CTX, pluginConfig, pluginComponents: EMPTY_PLUGIN_COMPONENTS })
//#then
const mergedMcp = config.mcp as Record<string, Record<string, unknown>>
@@ -89,6 +91,7 @@ describe("applyMcpConfig", () => {
const { applyMcpConfig } = await import("./mcp-config-handler")
await applyMcpConfig({
config,
ctx: TEST_CTX,
pluginConfig,
pluginComponents: {
...EMPTY_PLUGIN_COMPONENTS,
@@ -112,7 +115,7 @@ describe("applyMcpConfig", () => {
//#when
const { applyMcpConfig } = await import("./mcp-config-handler")
await applyMcpConfig({ config, pluginConfig, pluginComponents: EMPTY_PLUGIN_COMPONENTS })
await applyMcpConfig({ config, ctx: TEST_CTX, pluginConfig, pluginComponents: EMPTY_PLUGIN_COMPONENTS })
//#then
expect(loadMcpConfigsSpy).toHaveBeenCalledWith(["firecrawl", "exa"])
@@ -135,7 +138,7 @@ describe("applyMcpConfig", () => {
//#when
const { applyMcpConfig } = await import("./mcp-config-handler")
await applyMcpConfig({ config, pluginConfig, pluginComponents: EMPTY_PLUGIN_COMPONENTS })
await applyMcpConfig({ config, ctx: TEST_CTX, pluginConfig, pluginComponents: EMPTY_PLUGIN_COMPONENTS })
//#then
const mergedMcp = config.mcp as Record<string, Record<string, unknown>>
@@ -152,6 +155,7 @@ describe("applyMcpConfig", () => {
const { applyMcpConfig } = await import("./mcp-config-handler")
await applyMcpConfig({
config,
ctx: TEST_CTX,
pluginConfig,
pluginComponents: {
...EMPTY_PLUGIN_COMPONENTS,
@@ -166,4 +170,17 @@ describe("applyMcpConfig", () => {
expect(mergedMcp).not.toHaveProperty("plugin:custom")
})
test("passes the OpenCode workspace directory into built-in MCP config", async () => {
//#given
const config: Record<string, unknown> = { mcp: {} }
const pluginConfig = createPluginConfig()
//#when
const { applyMcpConfig } = await import("./mcp-config-handler")
await applyMcpConfig({ config, ctx: TEST_CTX, pluginConfig, pluginComponents: EMPTY_PLUGIN_COMPONENTS })
//#then
expect(createBuiltinMcpsSpy).toHaveBeenCalledWith([], pluginConfig, { cwd: TEST_CTX.directory })
})
})
+2 -1
View File
@@ -27,6 +27,7 @@ function captureUserDisabledMcps(
export async function applyMcpConfig(params: {
config: Record<string, unknown>;
ctx: { directory: string };
pluginConfig: OhMyOpenCodeConfig;
pluginComponents: PluginComponents;
}): Promise<void> {
@@ -47,7 +48,7 @@ export async function applyMcpConfig(params: {
}
const merged = {
...createBuiltinMcps(disabledMcps, params.pluginConfig),
...createBuiltinMcps(disabledMcps, params.pluginConfig, { cwd: params.ctx.directory }),
...mcpResult.servers,
...(userMcp ?? {}),
...params.pluginComponents.mcpServers,