refactor(opencode): expose MCP tools in native shape from the service (#35103)
This commit is contained in:
@@ -1,7 +1,6 @@
|
|||||||
import path from "node:path"
|
import path from "node:path"
|
||||||
import { pathToFileURL } from "node:url"
|
import { pathToFileURL } from "node:url"
|
||||||
import { LayerNode } from "@opencode-ai/core/effect/layer-node"
|
import { LayerNode } from "@opencode-ai/core/effect/layer-node"
|
||||||
import { type Tool } from "ai"
|
|
||||||
import { ConfigV1 } from "@opencode-ai/core/v1/config/config"
|
import { ConfigV1 } from "@opencode-ai/core/v1/config/config"
|
||||||
import { serviceUse } from "@opencode-ai/core/effect/service-use"
|
import { serviceUse } from "@opencode-ai/core/effect/service-use"
|
||||||
import { Client, type ClientOptions } from "@modelcontextprotocol/sdk/client/index.js"
|
import { Client, type ClientOptions } from "@modelcontextprotocol/sdk/client/index.js"
|
||||||
@@ -154,11 +153,19 @@ export interface ServerInstructions {
|
|||||||
tools: string[]
|
tools: string[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** An MCP tool in its native shape; consumers adapt it to their own tool format. */
|
||||||
|
export interface McpTool {
|
||||||
|
/** Shared cached definition; consumers must copy rather than mutate it. */
|
||||||
|
readonly def: MCPToolDef
|
||||||
|
readonly client: MCPClient
|
||||||
|
readonly timeout?: number
|
||||||
|
}
|
||||||
|
|
||||||
export interface Interface {
|
export interface Interface {
|
||||||
readonly status: () => Effect.Effect<Record<string, Status>>
|
readonly status: () => Effect.Effect<Record<string, Status>>
|
||||||
readonly clients: () => Effect.Effect<Record<string, MCPClient>>
|
readonly clients: () => Effect.Effect<Record<string, MCPClient>>
|
||||||
readonly instructions: () => Effect.Effect<ServerInstructions[]>
|
readonly instructions: () => Effect.Effect<ServerInstructions[]>
|
||||||
readonly tools: () => Effect.Effect<Record<string, Tool>>
|
readonly tools: () => Effect.Effect<Record<string, McpTool>>
|
||||||
readonly prompts: () => Effect.Effect<Record<string, PromptInfo & { client: string }>>
|
readonly prompts: () => Effect.Effect<Record<string, PromptInfo & { client: string }>>
|
||||||
readonly resources: (clientName?: string) => Effect.Effect<Record<string, ResourceInfo & { client: string }>>
|
readonly resources: (clientName?: string) => Effect.Effect<Record<string, ResourceInfo & { client: string }>>
|
||||||
readonly resourceTemplates: (
|
readonly resourceTemplates: (
|
||||||
@@ -656,7 +663,7 @@ const layer = Layer.effect(
|
|||||||
}
|
}
|
||||||
|
|
||||||
const tools = Effect.fn("MCP.tools")(function* () {
|
const tools = Effect.fn("MCP.tools")(function* () {
|
||||||
const result: Record<string, Tool> = {}
|
const result: Record<string, McpTool> = {}
|
||||||
const s = yield* InstanceState.get(state)
|
const s = yield* InstanceState.get(state)
|
||||||
|
|
||||||
const cfg = yield* cfgSvc.get()
|
const cfg = yield* cfgSvc.get()
|
||||||
@@ -672,9 +679,8 @@ const layer = Layer.effect(
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
const timeout = requestTimeout(s, clientName, mcpConfig, defaultTimeout)
|
const timeout = requestTimeout(s, clientName, mcpConfig, defaultTimeout)
|
||||||
for (const mcpTool of listed) {
|
for (const def of listed) {
|
||||||
const key = McpCatalog.toolName(clientName, mcpTool.name)
|
result[McpCatalog.toolName(clientName, def.name)] = { def, client, timeout }
|
||||||
result[key] = McpCatalog.convertTool(mcpTool, client, timeout)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { SessionV1 } from "@opencode-ai/core/v1/session"
|
|||||||
import { Provider } from "@/provider/provider"
|
import { Provider } from "@/provider/provider"
|
||||||
import { ProviderTransform } from "@/provider/transform"
|
import { ProviderTransform } from "@/provider/transform"
|
||||||
import { MCP } from "@/mcp"
|
import { MCP } from "@/mcp"
|
||||||
|
import { McpCatalog } from "@/mcp/catalog"
|
||||||
import { Permission } from "@/permission"
|
import { Permission } from "@/permission"
|
||||||
import { Tool } from "@/tool/tool"
|
import { Tool } from "@/tool/tool"
|
||||||
import { ToolJsonSchema } from "@/tool/json-schema"
|
import { ToolJsonSchema } from "@/tool/json-schema"
|
||||||
@@ -381,7 +382,8 @@ export const resolve = Effect.fn("SessionTools.resolve")(function* (input: {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const [key, item] of Object.entries(yield* mcp.tools())) {
|
for (const [key, entry] of Object.entries(yield* mcp.tools())) {
|
||||||
|
const item = McpCatalog.convertTool(entry.def, entry.client, entry.timeout)
|
||||||
const execute = item.execute
|
const execute = item.execute
|
||||||
if (!execute) continue
|
if (!execute) continue
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user