feat(mcp): append server instructions to context (#32490)

Co-authored-by: Aiden Cline <aidenpcline@gmail.com>
This commit is contained in:
4rcadia
2026-06-24 12:54:19 -04:00
committed by GitHub
parent 2e909334c1
commit e8e83afbce
8 changed files with 269 additions and 36 deletions
+8 -2
View File
@@ -1356,13 +1356,19 @@ export const layer = Layer.effect(
yield* plugin.trigger("experimental.chat.messages.transform", {}, { messages: msgs })
const [skills, env, instructions, modelMsgs] = yield* Effect.all([
const [skills, env, instructions, mcpInstructions, modelMsgs] = yield* Effect.all([
sys.skills(agent),
sys.environment(model),
instruction.system().pipe(Effect.orDie),
sys.mcp(agent, session.permission),
MessageV2.toModelMessagesEffect(msgs, model),
])
const system = [...env, ...instructions, ...(skills ? [skills] : [])]
const system = [
...env,
...instructions,
...(mcpInstructions ? [mcpInstructions] : []),
...(skills ? [skills] : []),
]
const format = lastUser.format ?? { type: "text" as const }
if (format.type === "json_schema") system.push(STRUCTURED_OUTPUT_SYSTEM_PROMPT)
const result = yield* handle.process({
+28 -2
View File
@@ -20,6 +20,8 @@ import { AbsolutePath } from "@opencode-ai/core/schema"
import { Location } from "@opencode-ai/core/location"
import { LocationServiceMap } from "@opencode-ai/core/location-layer"
import { Reference } from "@opencode-ai/core/reference"
import { MCP } from "@/mcp"
import { PermissionV1 } from "@opencode-ai/core/v1/permission"
export function provider(model: Provider.Model) {
if (model.api.id.includes("gpt-4") || model.api.id.includes("o1") || model.api.id.includes("o3"))
@@ -40,6 +42,7 @@ export function provider(model: Provider.Model) {
export interface Interface {
readonly environment: (model: Provider.Model) => Effect.Effect<string[]>
readonly skills: (agent: Agent.Info) => Effect.Effect<string | undefined>
readonly mcp: (agent: Agent.Info, permission?: PermissionV1.Ruleset) => Effect.Effect<string | undefined>
}
export class Service extends Context.Service<Service, Interface>()("@opencode/SystemPrompt") {}
@@ -48,6 +51,7 @@ export const layer = Layer.effect(
Service,
Effect.gen(function* () {
const skill = yield* Skill.Service
const mcp = yield* MCP.Service
const locations = yield* LocationServiceMap
return Service.of({
@@ -102,14 +106,36 @@ export const layer = Layer.effect(
Skill.fmt(list, { verbose: true }),
].join("\n")
}),
mcp: Effect.fn("SystemPrompt.mcp")(function* (agent: Agent.Info, permission?: PermissionV1.Ruleset) {
const ruleset = Permission.merge(agent.permission, permission ?? [])
const instructions = (yield* mcp.instructions()).filter(
(item) => item.tools.length === 0 || Permission.disabled(item.tools, ruleset).size < item.tools.length,
)
if (instructions.length === 0) return
return [
"<mcp_instructions>",
...instructions.flatMap((item) => [
` <server name="${item.name}">`,
...item.instructions.split("\n").map((line) => ` ${line}`),
" </server>",
]),
"</mcp_instructions>",
].join("\n")
}),
})
}),
)
export const defaultLayer = layer.pipe(Layer.provide(Skill.defaultLayer), Layer.provide(LocationServiceMap.layer))
export const defaultLayer = layer.pipe(
Layer.provide(Skill.defaultLayer),
Layer.provide(MCP.defaultLayer),
Layer.provide(LocationServiceMap.layer),
)
const locationServiceMapNode = LayerNode.make(LocationServiceMap.layer, [])
export const node = LayerNode.make(layer, [Skill.node, locationServiceMapNode])
export const node = LayerNode.make(layer, [Skill.node, MCP.node, locationServiceMapNode])
export * as SystemPrompt from "./system"