feat(mcp): restore Exa websearch support (#549)
* feat(mcp): restore Exa MCP websearch support - Add websearch.ts with Exa remote MCP configuration - Update McpNameSchema to include websearch - Wire websearch MCP into plugin initialization 🤖 GENERATED WITH ASSISTANCE OF [OhMyOpenCode](https://github.com/code-yeongyu/oh-my-opencode) * test(mcp): update tests and docs for websearch MCP - Update index.test.ts to verify 3 MCPs (websearch, context7, grep_app) - Add Exa/websearch documentation to README.md MCPs section 🤖 GENERATED WITH ASSISTANCE OF [OhMyOpenCode](https://github.com/code-yeongyu/oh-my-opencode)
This commit is contained in:
@@ -582,6 +582,7 @@ These tools enable agents to reference previous conversations and maintain conti
|
||||
- Use camelCase for function names
|
||||
```
|
||||
- **Online**: Project rules aren't everything. Built-in MCPs for extended capabilities:
|
||||
- **websearch**: Real-time web search powered by [Exa AI](https://exa.ai)
|
||||
- **context7**: Official documentation lookup
|
||||
- **grep_app**: Ultra-fast code search across public GitHub repos (great for finding implementation examples)
|
||||
|
||||
@@ -983,8 +984,9 @@ Available hooks: `todo-continuation-enforcer`, `context-window-monitor`, `sessio
|
||||
|
||||
### MCPs
|
||||
|
||||
Context7 and grep.app MCP enabled by default.
|
||||
Exa, Context7 and grep.app MCP enabled by default.
|
||||
|
||||
- **websearch**: Real-time web search powered by [Exa AI](https://exa.ai) - searches the web and returns relevant content
|
||||
- **context7**: Fetches up-to-date official documentation for libraries
|
||||
- **grep_app**: Ultra-fast code search across millions of public GitHub repositories via [grep.app](https://grep.app)
|
||||
|
||||
@@ -992,7 +994,7 @@ Don't want them? Disable via `disabled_mcps` in `~/.config/opencode/oh-my-openco
|
||||
|
||||
```json
|
||||
{
|
||||
"disabled_mcps": ["context7", "grep_app"]
|
||||
"disabled_mcps": ["websearch", "context7", "grep_app"]
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -10,9 +10,10 @@ describe("createBuiltinMcps", () => {
|
||||
const result = createBuiltinMcps(disabledMcps)
|
||||
|
||||
//#then
|
||||
expect(result).toHaveProperty("websearch")
|
||||
expect(result).toHaveProperty("context7")
|
||||
expect(result).toHaveProperty("grep_app")
|
||||
expect(Object.keys(result)).toHaveLength(2)
|
||||
expect(Object.keys(result)).toHaveLength(3)
|
||||
})
|
||||
|
||||
test("should filter out disabled built-in MCPs", () => {
|
||||
@@ -23,19 +24,21 @@ describe("createBuiltinMcps", () => {
|
||||
const result = createBuiltinMcps(disabledMcps)
|
||||
|
||||
//#then
|
||||
expect(result).toHaveProperty("websearch")
|
||||
expect(result).not.toHaveProperty("context7")
|
||||
expect(result).toHaveProperty("grep_app")
|
||||
expect(Object.keys(result)).toHaveLength(1)
|
||||
expect(Object.keys(result)).toHaveLength(2)
|
||||
})
|
||||
|
||||
test("should filter out both built-in MCPs when both disabled", () => {
|
||||
test("should filter out all built-in MCPs when all disabled", () => {
|
||||
//#given
|
||||
const disabledMcps = ["context7", "grep_app"]
|
||||
const disabledMcps = ["websearch", "context7", "grep_app"]
|
||||
|
||||
//#when
|
||||
const result = createBuiltinMcps(disabledMcps)
|
||||
|
||||
//#then
|
||||
expect(result).not.toHaveProperty("websearch")
|
||||
expect(result).not.toHaveProperty("context7")
|
||||
expect(result).not.toHaveProperty("grep_app")
|
||||
expect(Object.keys(result)).toHaveLength(0)
|
||||
@@ -49,9 +52,10 @@ describe("createBuiltinMcps", () => {
|
||||
const result = createBuiltinMcps(disabledMcps)
|
||||
|
||||
//#then
|
||||
expect(result).toHaveProperty("websearch")
|
||||
expect(result).not.toHaveProperty("context7")
|
||||
expect(result).toHaveProperty("grep_app")
|
||||
expect(Object.keys(result)).toHaveLength(1)
|
||||
expect(Object.keys(result)).toHaveLength(2)
|
||||
})
|
||||
|
||||
test("should handle empty disabled_mcps by default", () => {
|
||||
@@ -60,9 +64,10 @@ describe("createBuiltinMcps", () => {
|
||||
const result = createBuiltinMcps()
|
||||
|
||||
//#then
|
||||
expect(result).toHaveProperty("websearch")
|
||||
expect(result).toHaveProperty("context7")
|
||||
expect(result).toHaveProperty("grep_app")
|
||||
expect(Object.keys(result)).toHaveLength(2)
|
||||
expect(Object.keys(result)).toHaveLength(3)
|
||||
})
|
||||
|
||||
test("should only filter built-in MCPs, ignoring unknown names", () => {
|
||||
@@ -73,8 +78,9 @@ describe("createBuiltinMcps", () => {
|
||||
const result = createBuiltinMcps(disabledMcps)
|
||||
|
||||
//#then
|
||||
expect(result).toHaveProperty("websearch")
|
||||
expect(result).toHaveProperty("context7")
|
||||
expect(result).toHaveProperty("grep_app")
|
||||
expect(Object.keys(result)).toHaveLength(2)
|
||||
expect(Object.keys(result)).toHaveLength(3)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { websearch } from "./websearch"
|
||||
import { context7 } from "./context7"
|
||||
import { grep_app } from "./grep-app"
|
||||
import type { McpName } from "./types"
|
||||
@@ -5,6 +6,7 @@ import type { McpName } from "./types"
|
||||
export { McpNameSchema, type McpName } from "./types"
|
||||
|
||||
const allBuiltinMcps: Record<McpName, { type: "remote"; url: string; enabled: boolean }> = {
|
||||
websearch,
|
||||
context7,
|
||||
grep_app,
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { z } from "zod"
|
||||
|
||||
export const McpNameSchema = z.enum(["context7", "grep_app"])
|
||||
export const McpNameSchema = z.enum(["websearch", "context7", "grep_app"])
|
||||
|
||||
export type McpName = z.infer<typeof McpNameSchema>
|
||||
|
||||
|
||||
5
src/mcp/websearch.ts
Normal file
5
src/mcp/websearch.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
export const websearch = {
|
||||
type: "remote" as const,
|
||||
url: "https://mcp.exa.ai/mcp?tools=web_search_exa",
|
||||
enabled: true,
|
||||
}
|
||||
Reference in New Issue
Block a user