From 7fa52559cd431835e612cb27eefbd35cea7025d0 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Fri, 17 Jul 2026 22:15:10 +0000 Subject: [PATCH 1/3] Trim MCP server instructions and tool descriptions Deduplicate the MCP instruction surface per the documented principles in docs/contributing/documentation.md and mcp-server-patterns.md: - Server instructions no longer restate the search/execute tool descriptions, the per-capability job/session/service catalog (all discoverable via search), or the conversationId/memoryContext schema docs. The package lifecycle model, authoring lanes, credential rules, and guide pointers remain. - The search description drops authoring-lane and integration-bootstrap guidance now stated once in the server instructions. - The execute description keeps the full sandbox surface, gains the namespaced kody.remote/kody.mcp/kody.openapi accessor rule previously only in server instructions, and drops duplicated credential and bootstrap paragraphs. - Remove the now-unused conversationIdGuidance and repoRunCommandsExecuteSummary exports. Baseline static text shrinks from ~21.6k to ~11.3k chars (-48%). Co-authored-by: Kent C. Dodds --- .../repo/repo-run-commands-text.ts | 4 -- packages/worker/src/mcp/index.ts | 3 - .../worker/src/mcp/server-instructions.ts | 68 ++++--------------- packages/worker/src/mcp/tools/execute.ts | 25 ++----- packages/worker/src/mcp/tools/search.ts | 27 ++------ 5 files changed, 25 insertions(+), 102 deletions(-) diff --git a/packages/worker/src/mcp/capabilities/repo/repo-run-commands-text.ts b/packages/worker/src/mcp/capabilities/repo/repo-run-commands-text.ts index 3aa5c38e12..ec75ceea6c 100644 --- a/packages/worker/src/mcp/capabilities/repo/repo-run-commands-text.ts +++ b/packages/worker/src/mcp/capabilities/repo/repo-run-commands-text.ts @@ -42,7 +42,3 @@ export const repoRunCommandsCommandsFieldDescription = [ repoRunCommandsUnsupportedSyntaxDescription, repoRunCommandsSupportedFormsDescription, ].join('\n') - -export const repoRunCommandsExecuteSummary = [ - 'commands are newline-separated, parsed, git-only workflows, not shell execution', -].join(' ') diff --git a/packages/worker/src/mcp/index.ts b/packages/worker/src/mcp/index.ts index 88dac6dcdf..4dc8116c46 100644 --- a/packages/worker/src/mcp/index.ts +++ b/packages/worker/src/mcp/index.ts @@ -8,7 +8,6 @@ import { buildSentryOptions } from '../sentry-options.ts' import { parseMcpCallerContext, type McpServerProps } from './context.ts' import { buildMcpServerInstructions, - conversationIdGuidance, type RemoteConnectorInstructionSummary, } from './server-instructions.ts' import { registerTools } from './register-tools.ts' @@ -27,8 +26,6 @@ export type State = { } export type Props = McpServerProps -export { conversationIdGuidance } - async function loadRemoteConnectorInstructionSummaries(input: { env: Env caller: McpCallerContext diff --git a/packages/worker/src/mcp/server-instructions.ts b/packages/worker/src/mcp/server-instructions.ts index 54255f83f2..d53dbe8a02 100644 --- a/packages/worker/src/mcp/server-instructions.ts +++ b/packages/worker/src/mcp/server-instructions.ts @@ -40,9 +40,6 @@ ${lines.join('\n')} ` } -export const conversationIdGuidance = - 'The public MCP tools accept optional `conversationId` and `memoryContext` fields. `conversationId` ties related calls together. If you already have a `conversationId` from an earlier response in the same conversation, pass it back unchanged. Otherwise omit this field to receive a server-generated ID, then reuse the returned `conversationId` on subsequent calls - this enables optimizations like reduced response size. Do not invent your own `conversationId`.' - export function buildBaseMcpServerInstructions( input: { domains?: ReadonlyArray @@ -55,66 +52,31 @@ End-user documentation (workflows, secrets, troubleshooting): https://github.com/kentcdodds/kody/tree/main/docs/use Package lifecycle (use this as the primary mental model): -1. Discover and invoke before building: use \`search\` to find an existing built-in capability, connected capability, or saved package. Inspect the entity detail for its exact call shape, then invoke it rather than reimplementing it. -2. Explore temporarily: use \`execute\` for quick one-off work, capability composition, authenticated smoke tests, and experiments. Treat execute modules as ephemeral, not as the durable home for behavior. -3. Create or evolve a repo-backed package: use a package when behavior should be reused, maintained, tested, exposed as an app or service, or given a package-owned schedule as part of named or evolving behavior. Search once more before creating one so you extend an existing package when that is the better fit. +1. Discover and invoke before building: use \`search\` to find an existing built-in capability, connected capability, or saved package, inspect the entity detail for its exact call shape, then invoke it rather than reimplementing it. +2. Explore temporarily: use \`execute\` for quick one-off work, capability composition, authenticated smoke tests, and experiments. Execute modules are ephemeral, not the durable home for behavior. +3. Create or evolve a repo-backed package when behavior should be reused, maintained, tested, exposed as an app or service, or given a package-owned schedule. Search once more before creating one so you extend an existing package when that is the better fit. -Signals to escalate from \`execute\` to a package: -- The user wants reusable named behavior, expects to keep improving it, or wants its schedule to evolve with the implementation. -- The code is becoming a named workflow or needs multiple files, dependencies, tests, binary assets, version history, or review. -- The behavior needs a durable surface such as package exports, package-owned jobs, an app, or a service. -- You are repeating or incrementally editing substantially the same execute module. Stop accumulating ephemeral code and move it into a package. -- Keep genuinely one-off exploration in \`execute\`; do not create a package merely because a task required code. -- Scheduling alone does not require a package. Use a package-owned job when the schedule belongs to reusable, evolving, or named package behavior. Use \`job_schedule\` directly for a genuinely ad hoc or one-off job, or a simple self-contained schedule that is not tied to a reusable package. +Escalate from \`execute\` to a package when the user wants reusable named behavior they expect to keep improving, when the code needs multiple files, dependencies, tests, binary assets, version history, or review, when the behavior needs a durable surface (package exports, package-owned jobs, an app, or a service), or when you are repeatedly editing substantially the same execute module. Keep genuinely one-off exploration in \`execute\`. Scheduling alone does not require a package: use \`job_schedule\` for ad hoc or simple self-contained schedules and package-owned jobs when the schedule belongs to reusable, evolving package behavior. Load \`coding_guide_get({ guide: "package_lifecycle" })\` when the escalation call is unclear. -Choose the package authoring lane before building: -- Coding agents with local filesystem/git access should use the git lane: \`package_get_git_remote\` (pass \`create: true\` with a new \`kody_id\` to register a stub package and mint its remote in one call), clone into a temporary directory, edit and test normally (binary assets supported), push, then publish with \`package_publish_external_push\`. -- Tool-only agents should use \`package_save\` and repo sessions. \`package_save\` creates or replaces a repo-backed package rooted at \`package.json\` from the complete UTF-8 text file set. -- If package work needs binary assets, many-file changes, or local build/test loops and you lack local filesystem/git access, tell the user it fits a coding-capable agent better and confirm before proceeding tool-only. -- Standard package exports define the package surface. \`package.json#kody\` contains Kody-specific metadata such as tags, optional app config, and package-owned jobs. When creating or materially changing a package, keep a root \`README.md\` \`## Intent\` section with the user's goal; ask the user if unclear and update it when scope expands. +Package authoring lanes: +- Coding agents with local filesystem/git access: \`package_get_git_remote\` (pass \`create: true\` with a new \`kody_id\` to register a stub package and mint its remote in one call), clone into a temporary directory, edit and test normally (binary assets supported), push, then publish with \`package_publish_external_push\`. +- Tool-only agents: \`package_save\` (creates or replaces a repo-backed package rooted at \`package.json\` from the complete UTF-8 text file set) plus \`repo_*\` sessions. If the work needs binary assets, many-file changes, or local build/test loops, tell the user it fits a coding-capable agent better and confirm before proceeding tool-only. +- When creating or materially changing a package, load \`coding_guide_get({ guide: "package_authoring" })\` and keep a root \`README.md\` \`## Intent\` section with the user's goal; ask the user if unclear and update it when scope expands. -Conventions -- ${conversationIdGuidance} -- \`memoryContext\`: short and task-focused. Kody may use it to surface a few relevant long-term memories and suppress repeats within the same \`conversationId\`. +Conventions: +- Both tools accept optional \`conversationId\` and \`memoryContext\` fields (documented in their input schemas); reuse the returned \`conversationId\` across related calls. - Credential setup uses the standard setup pages: \`/connect/oauth\` for OAuth integrations and reconnects, \`/account/secrets/new\` for API keys, PATs, and other user-provided secrets. Never ask users to paste secrets, tokens, API keys, passwords, or credentials into chat. -- \`package_get\` / \`package_list\` / \`package_update\` / \`package_delete\`: inspect or manage saved packages for the signed-in user. \`package_update({ package_id, changes: { hidden } })\` changes mutable settings; package.json-derived metadata changes through save or publish. -- Integration-backed work: use \`search\` and official guides before local repo exploration. For packages, package apps, or workflows that depend on third-party auth, first call \`coding_guide_get\` with \`guide: "integration_bootstrap"\`, confirm the required \`integration\` or \`secret\` entity exists through \`search\`, run a cheap authenticated \`execute\` smoke test, then build. If setup is missing, load \`oauth\` for \`/connect/oauth\`, \`connect_secret\` for secret collection, and \`secret_backed_integration\` for the default non-OAuth recipe. -- \`job_list\` / \`job_get\`: inspect the signed-in user's scheduled jobs, recent run outcomes, and current per-user alarm state when debugging scheduling issues. Pass \`includeCode: true\` to \`job_get\` when you need the stored repo-backed job source entrypoint and code. -- \`job_schedule\`: schedule a repo-backed job for the signed-in user without creating a saved package first. It is appropriate for genuinely ad hoc or one-off jobs and simple self-contained schedules not tied to a reusable package. Supports one-off, interval, and cron schedules. -- \`job_schedule_once\`: compatibility wrapper for one-off repo-backed jobs when you only need a single run time. -- \`job_update\`: update an existing scheduled job by id. Supports safe mutable fields such as name, code, params, schedule, timezone, enabled, and kill-switch state. Providing \`code\` publishes a new commit on the job's repo-backed source (the simplest way to change the job module for non-package jobs); the replacement must default export a function and read \`params\` from its first argument, not from \`kody:runtime\`. -- \`job_delete\`: delete one of the signed-in user's scheduled jobs by id. -- \`job_run_now\`: run an existing scheduled job immediately by id and return the updated job view plus execution result for debugging. -- \`workflow_run_list\`: inspect recent Cloudflare Workflow runs created through \`kody:runtime\` \`workflows.create\`; use it after durable long-running work such as batch sweeps, migrations, and polling loops. -- Package jobs are schedules owned by reusable, evolving, or named package behavior. For genuinely ad hoc or one-off jobs and simple self-contained schedules not tied to a reusable package, use \`job_schedule\`. Package apps are optional UI surfaces declared by the package, and packages may also declare headless package services for long-lived background runtimes. -- Package apps can also use Kody-managed realtime websocket sessions through \`session_list\`, \`session_emit\`, and \`session_broadcast\`, and package jobs can emit to those sessions when running under the same package caller context. -- Package services are inspected and controlled through \`service_list\`, \`service_get\`, \`service_start\`, and \`service_stop\`. -- Memory writes are verify-first: always run \`meta_memory_verify\` before \`meta_memory_upsert\` or \`meta_memory_delete\`. Kody retrieves related memories; the consuming agent decides whether to upsert, delete, both, or do nothing. \`meta_memory_upsert\` creates a new memory when \`memory_id\` is omitted and updates an existing memory when \`memory_id\` is provided. -- User-specific MCP instructions: \`meta_get_mcp_server_instructions\` / \`meta_set_mcp_server_instructions\` (signed-in users). Updates apply to **new** MCP sessions (reconnect to refresh what the host shows). -- Kody friction: when capabilities, packages, memories, or guides create avoidable friction, call \`coding_guide_get\` with \`guide: "platform_friction"\`; mention the friction to the user, ask before memory changes, and make obvious local docs/package improvements when already in scope. +- Integration-backed work: before building packages, package apps, or workflows that depend on third-party auth, call \`coding_guide_get({ guide: "integration_bootstrap" })\`, confirm the required \`integration\` or \`secret\` entity exists through \`search\`, and run a cheap authenticated \`execute\` smoke test. Do not present auth-dependent work as complete until that smoke test succeeds. +- Jobs, workflows, sessions, services, values, storage, and the other capability groups below are individual capabilities: discover them with \`search\`, whose entity detail includes each capability's exact call shape. +- Memory writes are verify-first: run \`meta_memory_verify\` before \`meta_memory_upsert\` or \`meta_memory_delete\`. +- User-specific MCP instructions: \`meta_get_mcp_server_instructions\` / \`meta_set_mcp_server_instructions\` (signed-in users). Updates apply to **new** MCP sessions. +- When Kody capabilities, packages, memories, or guides create avoidable friction, load \`coding_guide_get({ guide: "platform_friction" })\`, mention the friction to the user, and ask before memory changes. Kody repository (for contributors): https://github.com/kentcdodds/kody Domains (builtin capability groups) ${domainInstructions} ${formatRemoteConnectorInstructions(input.remoteConnectors)} - -What shows up in \`search\` (before you search) -- Result **types**: \`capability\` (built-in or connected remote connector), \`package\` (saved repo-backed package), \`value\` (persisted non-secret config), \`integration\` (saved integration config), \`secret\` (metadata only). Use \`entity: "{id}:{type}"\` for one item’s detail. - -search -- \`query\`: natural language results are ranked (order matters). An entire saved-package UUID, kody id, current-origin \`/account/packages/:packageId\` URL, or owner-matching \`/@username/packages/:kodyId\` URL resolves as exact user-scoped package identity instead of competing with semantic results. Hidden exact queries require \`includeHiddenPackages: true\`. Optional \`limit\`, \`maxResponseSize\`. -- \`entity: "{id}:{type}"\` (\`capability\` | \`package\` | \`value\` | \`integration\` | \`secret\`) for one entity’s detail. Package ids may be UUIDs or kody ids and hidden packages resolve here regardless of \`includeHiddenPackages\`. Capability detail includes an exact execute snippet and TypeScript call shapes; other entity details include usage. If a natural-language \`query\` returns no useful hits, rephrase or call \`meta_list_capabilities\` — \`entity\` does not repair an empty ranked list. -- Examples: - - search({ query: 'saved package for github automation' }) - - search({ query: 'Cloudflare API zones dns workers d1' }) - - search({ entity: 'coding_guide_get:capability' }) - -execute -- Single ESM module string with a default export such as \`export default async function main(input = {}) { ... }\`; \`params\` are passed as the first argument. Import runtime APIs from \`kody:runtime\`. Example: \`import { kody, refreshAccessToken, createAuthenticatedFetch, oauthClientCredentials, secretHeaders, workflows } from 'kody:runtime'\`. Built-in capabilities returned by \`search\` are available through \`kody\`: use \`await kody.capability_id(input)\` for valid identifier names or \`await kody["capability-id"](input)\` for non-identifier ids. Remote connector capabilities are deliberately separate: use \`await kody.remote["name"].capability_name(input)\` (for example \`kody.remote["home"].set_pin({ pin })\`), never a flat \`kody.kind_instance_capability(...)\` call. Tools from user-added MCP servers follow the same pattern through \`await kody.mcp["server-name"].tool_name(input)\`; manage those servers with the \`mcp_servers\` capabilities or /account/mcp-servers. Curated OpenAPI provider operations use \`await kody.openapi["name"].operation_slug(input)\`; manage bindings with the \`openapi\` domain (\`openapi_binding_save\` / list / get / delete / refresh). \`workflows.create\` can queue inline \`code\` or a saved-package \`exportName\`; prefer it for durable, retryable, inspectable work that may outlive execute's timeout, while plain execute is for quick single operations. Use \`secretHeaders.basic(...)\` or \`oauthClientCredentials(...)\` for client-credentials Basic Auth instead of asking users to precompute a Basic header. Prefer one \`execute\` when the plan is clear. Full rules for \`fetch\`, placeholders, \`secret_list\` / \`value_get\`, and \`x-kody-secret\`: see the \`execute\` tool description. -- Cross-package imports use specifiers such as \`kody:@scope/my-package/export-name\`. For dynamic current-version calls inside package runtime code or authenticated execute calls, prefer \`packages.invokeChecked({ kodyId, exportName, params })\` or \`packages.check(...)\` followed by \`packages.invoke(check.invoke)\`; use static imports for library-like bundled snapshots. Saved package names must be scoped (\`@scope/\`) and the leaf segment must match \`kody.id\`. Package jobs are owned by packages, ad hoc jobs can be scheduled with \`job_schedule\`, and package apps are optional package surfaces. -- Official how-to guides from the Kody repo: when creating or materially changing a package, call \`coding_guide_get\` with \`guide: "package_authoring"\`. If the package, package app, or workflow depends on a third-party integration, secrets, or OAuth, call \`guide: "integration_bootstrap"\` before building the dependent package. If unsure, \`search\` for this capability and load the right guide before implementing. -- Do not save or present an auth-dependent package as complete until \`search\` shows the required integration or secret reference exists and a minimal authenticated \`execute\` smoke test succeeds. `.trim() } diff --git a/packages/worker/src/mcp/tools/execute.ts b/packages/worker/src/mcp/tools/execute.ts index 328b1efb97..2c4dcb7f93 100644 --- a/packages/worker/src/mcp/tools/execute.ts +++ b/packages/worker/src/mcp/tools/execute.ts @@ -36,7 +36,6 @@ import { formatSurfacedMemoriesMarkdown, surfaceToolMemories, } from './memory-tool-context.ts' -import { repoRunCommandsExecuteSummary } from '#mcp/capabilities/repo/repo-run-commands-text.ts' import { finishToolTiming, startToolTiming } from './tool-timing.ts' import { prependToolMetadataContent } from './tool-response-content.ts' import { @@ -57,37 +56,25 @@ Run one ephemeral ESM module string with a default export. Imports may be arbitr Projection rule: you write the code -- if a call returns a large response, project the fields you need before returning. Never return raw API responses; extract a slim shape (e.g. \`{ id, subject, snippet }\`) or a summary. -Saved package surface: -- \`package_save\`, \`package_get\`, \`package_list\`, \`package_delete\` -- repo-backed package editing with \`repo_run_commands\`; ${repoRunCommandsExecuteSummary} -- cross-package imports with specifiers such as - \`kody:@scope/my-package/export-name\` -- When creating or materially changing a package, load \`coding_guide_get({ guide: 'package_authoring' })\` and keep a root \`README.md\` \`## Intent\` section with the user-defined goal. - Sandbox surface: - Import runtime helpers from \`kody:runtime\`. - \`import { kody } from 'kody:runtime'\` for builtin capabilities discovered by \`search\`; call valid identifier names as \`await kody.capability_id(input)\`. If a capability id is not a valid JavaScript identifier, use bracket notation: \`await kody["capability-id"](input)\`. Capability detail from \`search({ entity: "{name}:capability" })\` includes the exact snippet. +- Remote connector, user-added MCP server, and curated OpenAPI capabilities use namespaced accessors: \`await kody.remote["name"].capability_name(input)\`, \`await kody.mcp["server-name"].tool_name(input)\`, and \`await kody.openapi["name"].operation_slug(input)\` — never a flat \`kody.kind_instance_capability(...)\` call. - \`import { storage } from 'kody:runtime'\` for durable storage helpers on the bound \`storageId\`, including \`storage.sql(query, params?)\`. \`storage.sql\` returns \`{ columns, rows, rowCount, rowsRead, rowsWritten }\`; read query rows from \`.rows\`. -- \`import { refreshAccessToken, createAuthenticatedFetch, oauthClientCredentials, secretHeaders } from 'kody:runtime'\` for OAuth integrations and secret-derived auth headers. Integration \`name\` may be account-specific (e.g. \`google-personal\`, \`google-business\`); call \`integration_list\` first when the task involves a provider that may have multiple accounts connected. For APIs such as PayPal that require client-credentials Basic Auth, save the client id and client secret separately and use \`secretHeaders.basic({ usernameSecret: 'paypalClientId', passwordSecret: 'paypalClientSecret', scope: 'user' })\` in the Authorization header, or \`oauthClientCredentials(...)\` for the token request. Do not ask users to precompute or save a derived Basic header. +- \`import { refreshAccessToken, createAuthenticatedFetch, oauthClientCredentials, secretHeaders } from 'kody:runtime'\` for OAuth integrations and secret-derived auth headers. Integration \`name\` may be account-specific (e.g. \`google-personal\`, \`google-business\`); call \`integration_list\` first when a provider may have multiple accounts connected. For client-credentials Basic Auth, save the id and secret separately and use \`secretHeaders.basic({ usernameSecret, passwordSecret, scope })\` in the Authorization header, or \`oauthClientCredentials(...)\` for the token request; do not ask users to precompute a derived Basic header. - \`import { workflows } from 'kody:runtime'\` for durable Cloudflare Workflows. \`workflows.create\` accepts either inline \`code\` or a saved-package \`exportName\`; use \`workflow_run_list\` to inspect recent runs. - Execute has a hard timeout (~90s by default). For batch sweeps, migrations, polling loops, or work likely to run >~60s, submit one durable \`workflows.create({ code, params })\` from a single execute call instead of chaining many MCP round-trips. - Optional \`params\` are passed as the first argument to the module default export. Prefer \`export default async function main(input = {}) { ... }\`; pass \`input\` to shared helpers explicitly. - \`import { packageContext } from 'kody:runtime'\` in saved package code when you need package metadata; it is \`null\` for ad hoc execute calls. -- \`import { packages } from 'kody:runtime'\` exposes \`packages.check(...)\`, \`packages.invoke(...)\`, and \`packages.invokeChecked(...)\` in saved package runtime contexts and authenticated ad hoc execute calls. Prefer \`invokeChecked\` for dynamic current-version package calls unless you already called \`check\` and pass \`check.invoke\` to \`invoke\`. -- \`fetch(...)\` is the host-provided network global; \`{{secret:name}}\` / \`{{secret:name|scope=user}}\` work in URL, headers, or body on approved hosts only. \`secretHeaders.basic(...)\` returns an opaque placeholder for fetch headers; the gateway resolves both referenced secrets, enforces host approval for both, and sends only the derived Basic header. +- \`import { packages } from 'kody:runtime'\` exposes \`packages.check(...)\`, \`packages.invoke(...)\`, and \`packages.invokeChecked(...)\` in saved package runtime contexts and authenticated ad hoc execute calls. Prefer \`invokeChecked\` for dynamic current-version package calls. Static cross-package imports such as \`kody:@scope/my-package/export-name\` bundle a published snapshot. +- \`fetch(...)\` is the host-provided network global; \`{{secret:name}}\` / \`{{secret:name|scope=user}}\` work in URL, headers, or body on approved hosts only. \`secretHeaders.basic(...)\` returns an opaque placeholder for fetch headers; the gateway resolves both referenced secrets, enforces host approval for both, and sends only the derived Basic header. For host approval failures, use the error’s approval path. - Fields marked \`x-kody-secret: true\` accept the same placeholder form; respect per-secret allowed-capability lists. -- Placeholders are not general string interpolation (they do not resolve in arbitrary return values). -- Never place placeholder text into user-visible or third-party-visible content such as issue bodies, comments, prompts, logs, or returned strings. If you need to describe a placeholder literally, obfuscate it instead of embedding the exact \`{{secret:...}}\` token into content that may be sent over \`fetch\`. -- \`await kody.secret_list({ scope? })\` — metadata only. \`secret_set\` — persist values already in trusted execution (e.g. refreshed tokens); write-only. -- No \`secret_get\` / \`secrets\` helpers in the sandbox. +- Placeholders are not general string interpolation (they do not resolve in arbitrary return values). Never place placeholder text into user-visible or third-party-visible content such as issue bodies, comments, prompts, logs, or returned strings; obfuscate the \`{{secret:...}}\` token if you must describe it literally. +- \`await kody.secret_list({ scope? })\` — metadata only. \`secret_set\` — persist values already in trusted execution (e.g. refreshed tokens); write-only. No \`secret_get\` / \`secrets\` helpers in the sandbox. - \`value_get\` / \`value_list\` for non-secret persisted config. -Credential collection and rotation use standard Kody setup pages: \`/connect/oauth\` for OAuth integrations and \`/account/secrets/new\` for API keys, PATs, and other user-provided secrets. Never ask users to paste secrets, tokens, API keys, passwords, or credentials into chat. For host approval failures, use the error’s approval path. - Prefer one \`execute\` when the workflow is clear; split calls when you need new user input or a changed plan. -For integration-backed packages, package apps, or workflows, use \`search\` and \`coding_guide_get({ guide: 'integration_bootstrap' })\` before building. Confirm the needed \`integration\` or \`secret\` entity exists, then run a cheap read-only authenticated smoke test in \`execute\` (for example a profile/viewer endpoint) before \`package_save\`, package app work, or workflow scheduling. If credentials are missing, load the matching official guide: \`oauth\`, \`connect_secret\`, or \`secret_backed_integration\`. - Example: \`import { kody } from 'kody:runtime' diff --git a/packages/worker/src/mcp/tools/search.ts b/packages/worker/src/mcp/tools/search.ts index 09c84dc034..2566bfccf4 100644 --- a/packages/worker/src/mcp/tools/search.ts +++ b/packages/worker/src/mcp/tools/search.ts @@ -1771,27 +1771,10 @@ without competing semantic matches. Hidden exact queries require related lookups in one call. Capability detail includes an exact \`execute\` module snippet plus TypeScript call-shape definitions by default. Synthesized provider capabilities (OpenAPI, MCP server, remote connector) also list related -operations from the same provider. - -Packages: \`package_list\` and \`package_get\` to inspect. Coding agents with -local filesystem/git access author via \`package_get_git_remote\` -(\`create: true\` for new packages) + clone-edit-push + -\`package_publish_external_push\`; tool-only agents use \`package_save\` and -\`repo_*\`. For package creation or material updates, load \`coding_guide_get\` -with \`guide: "package_authoring"\` and maintain a root README.md Intent section. -Open package apps through their hosted package URLs. -Secrets: results expose metadata; use \`kody.secret_list\` during execute, -\`/account/secrets/new\` for API key/PAT entry and rotation, and -\`/connect/oauth\` for OAuth integrations. -Persisted values use \`kody.value_get\` / \`kody.value_list\`. Integrations -use \`kody.integration_get\` / \`kody.integration_list\`. - -Integration-backed packages, package apps, and workflows: search for the provider -and \`coding_guide_get\`, inspect exact \`integration\` or \`secret\` entities, -load \`guide: "integration_bootstrap"\`, and continue only after a cheap -authenticated \`execute\` smoke test succeeds. If setup is missing, use the guide -that matches the auth path: \`oauth\`, \`connect_secret\`, or -\`secret_backed_integration\`. +operations from the same provider. Package ids may be UUIDs or kody ids, and +hidden packages resolve here regardless of \`includeHiddenPackages\`. + +Secret results expose metadata only; credential values never appear. If results look incomplete: \`meta_list_capabilities\` (full registry) or \`meta_list_remote_connector_status\` (remote connectors). @@ -1799,8 +1782,6 @@ If results look incomplete: \`meta_list_capabilities\` (full registry) or Optional **limit** (default 15) and **maxResponseSize** trim low-ranked results. Example arguments: - \`{ "query": "saved github automation package", "limit": 10 }\` -- \`{ "query": "preferred org value or saved integration", "limit": 10 }\` -- \`{ "query": "package with worker app ui", "limit": 10 }\` - \`{ "entity": "coding_guide_get:capability" }\` - \`{ "entity": ["openapi:canva:createdesignexportjob:capability", "openapi:canva:getdesignexportjob:capability"] }\` - \`{ "entity": "user:preferred_org:value" }\` From a4fd21a324d74e7b5c1466ffc7894ef59f9ca06c Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Fri, 17 Jul 2026 22:30:35 +0000 Subject: [PATCH 2/3] Tighten builtin capability domain descriptions Domain descriptions render into the per-session server instructions domain list. Trim the nine verbose ones (integrations, openapi, admin, community, mcp_servers, packages, meta, secrets, coding) by dropping operational detail that already lives on the individual capability descriptions or in the server-instruction conventions, keeping the scope and safety framing of each group. Builtin domain description text shrinks from ~4.0k to ~2.8k chars. Co-authored-by: Kent C. Dodds --- packages/worker/src/mcp/capabilities/admin/domain.ts | 2 +- packages/worker/src/mcp/capabilities/coding/domain.ts | 2 +- packages/worker/src/mcp/capabilities/community/domain.ts | 2 +- packages/worker/src/mcp/capabilities/integrations/domain.ts | 2 +- packages/worker/src/mcp/capabilities/mcp-servers/domain.ts | 2 +- packages/worker/src/mcp/capabilities/meta/domain.ts | 2 +- packages/worker/src/mcp/capabilities/openapi/domain.ts | 2 +- packages/worker/src/mcp/capabilities/packages/domain.ts | 2 +- packages/worker/src/mcp/capabilities/secrets/domain.ts | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/worker/src/mcp/capabilities/admin/domain.ts b/packages/worker/src/mcp/capabilities/admin/domain.ts index cd8af0061e..cee64f4aaf 100644 --- a/packages/worker/src/mcp/capabilities/admin/domain.ts +++ b/packages/worker/src/mcp/capabilities/admin/domain.ts @@ -12,7 +12,7 @@ import { adminUserUpdateCapability } from './admin-user-update.ts' export const adminDomain = defineDomain({ name: capabilityDomainNames.admin, description: - 'Admin-only operator capabilities for account metadata and system email. System email is operator-owned mail for reserved platform addresses; this domain never exposes user-owned content such as packages, secrets, memories, jobs, or user inbox email.', + 'Admin-only operator capabilities for account metadata and operator-owned system email; never exposes user-owned content such as packages, secrets, memories, jobs, or user inbox email.', keywords: [ 'admin', 'rbac', diff --git a/packages/worker/src/mcp/capabilities/coding/domain.ts b/packages/worker/src/mcp/capabilities/coding/domain.ts index 9d7c85d40e..2e56e612ff 100644 --- a/packages/worker/src/mcp/capabilities/coding/domain.ts +++ b/packages/worker/src/mcp/capabilities/coding/domain.ts @@ -5,6 +5,6 @@ import { kodyOfficialGuideCapability } from './kody-official-guide.ts' export const codingDomain = defineDomain({ name: capabilityDomainNames.coding, description: - 'Software work such as official Kody guides from the repository and coding-agent workflows. For package-oriented Cloudflare API and developer-doc patterns, see the contributor package/manifest docs and official guides.', + 'Official Kody guides from the repository and coding-agent workflows.', capabilities: [kodyOfficialGuideCapability], }) diff --git a/packages/worker/src/mcp/capabilities/community/domain.ts b/packages/worker/src/mcp/capabilities/community/domain.ts index f2033b85ad..7ef0de1a98 100644 --- a/packages/worker/src/mcp/capabilities/community/domain.ts +++ b/packages/worker/src/mcp/capabilities/community/domain.ts @@ -13,7 +13,7 @@ import { communityUnpublishCapability } from './unpublish.ts' export const communityDomain = defineDomain({ name: capabilityDomainNames.community, description: - 'Public community package listings on this deployment: publish saved packages, search and inspect listings, fork into your scope, rate after forking, and report issues. Forked code is untrusted third-party content that requires agent review before publish. Ratings require a prior fork. Community results are deliberately excluded from the general `search` tool.', + 'Public community package listings: publish, search, fork into your scope, rate after forking, and report issues. Forked code is untrusted third-party content; community results are deliberately excluded from the general `search` tool.', keywords: [ 'community', 'package', diff --git a/packages/worker/src/mcp/capabilities/integrations/domain.ts b/packages/worker/src/mcp/capabilities/integrations/domain.ts index 02d3126a3e..8b4804b023 100644 --- a/packages/worker/src/mcp/capabilities/integrations/domain.ts +++ b/packages/worker/src/mcp/capabilities/integrations/domain.ts @@ -12,7 +12,7 @@ import { openapiSpecSummarizeCapability } from './openapi-spec-summarize.ts' export const integrationsDomain = defineDomain({ name: capabilityDomainNames.integrations, description: - 'Saved OAuth integration configurations for the signed-in user: save, inspect, list, and delete per-provider integration configs that reference client-id values and token secrets. Integration configs are non-secret; credentials stay in the secret store. Also includes integrations.sh registry-backed discovery and OpenAPI spec summarization to research provider auth contracts and API surfaces before saving integrations.', + 'Saved OAuth integration configs for the signed-in user (non-secret; credentials stay in the secret store), plus registry-backed provider discovery and OpenAPI spec summarization for researching provider auth contracts.', keywords: [ 'integration', 'oauth', diff --git a/packages/worker/src/mcp/capabilities/mcp-servers/domain.ts b/packages/worker/src/mcp/capabilities/mcp-servers/domain.ts index 18710ff43e..eece894900 100644 --- a/packages/worker/src/mcp/capabilities/mcp-servers/domain.ts +++ b/packages/worker/src/mcp/capabilities/mcp-servers/domain.ts @@ -10,7 +10,7 @@ import { mcpServerSetEnabledCapability } from './mcp-server-set-enabled.ts' export const mcpServersDomain = defineDomain({ name: capabilityDomainNames.mcpServers, description: - 'User-added remote MCP servers that Kody connects to as a client: add (with OAuth support), list with live status, reconnect, refresh tools, enable/disable, and remove. Tools from connected servers appear as synthesized mcp: capability domains callable via kody.mcp["server-name"].tool_name(...).', + 'User-added remote MCP servers that Kody connects to as a client: add, list with live status, reconnect, refresh tools, enable/disable, and remove. Connected servers surface as mcp: domains callable via kody.mcp["server-name"].tool_name(...).', keywords: [ 'mcp', 'server', diff --git a/packages/worker/src/mcp/capabilities/meta/domain.ts b/packages/worker/src/mcp/capabilities/meta/domain.ts index d45d461fbf..98bde053ca 100644 --- a/packages/worker/src/mcp/capabilities/meta/domain.ts +++ b/packages/worker/src/mcp/capabilities/meta/domain.ts @@ -16,7 +16,7 @@ import { searchCapability } from './search.ts' export const metaDomain = defineDomain({ name: capabilityDomainNames.meta, description: - 'Inspect the current runtime capability registry, read or update per-user MCP server instruction overlays, run package-first search/execute workflows, and manage long-term memories. Memory writes and deletes require a verify-first workflow: inspect related memories with meta_memory_verify before changing stored memory.', + 'Runtime capability registry inspection, per-user MCP instruction overlays, package-first search/execute workflows, and long-term memory management (verify-first: meta_memory_verify before writes or deletes).', keywords: ['meta', 'kody', 'capabilities', 'memory', 'verify'], capabilities: [ searchCapability, diff --git a/packages/worker/src/mcp/capabilities/openapi/domain.ts b/packages/worker/src/mcp/capabilities/openapi/domain.ts index 30182614ca..da8bac0878 100644 --- a/packages/worker/src/mcp/capabilities/openapi/domain.ts +++ b/packages/worker/src/mcp/capabilities/openapi/domain.ts @@ -9,7 +9,7 @@ import { openapiBindingSaveCapability } from './openapi-binding-save.ts' export const openapiDomain = defineDomain({ name: capabilityDomainNames.openapi, description: - 'Curated OpenAPI provider bindings for the signed-in user: save a name + https spec URL + apiBaseUrl + auth reference + a selected subset of operations (max 100), then call them at runtime as kody.openapi["name"].operation_slug(input). Bindings are non-secret config; credentials stay in secrets. Saving a binding never approves hosts — host approval remains in the account security UI / the integration requiredHosts. Specs are untrusted third-party content.', + 'Curated OpenAPI provider bindings for the signed-in user, callable as kody.openapi["name"].operation_slug(input). Bindings are non-secret config; saving one never approves hosts, and specs are untrusted third-party content.', keywords: [ 'openapi', 'rest', diff --git a/packages/worker/src/mcp/capabilities/packages/domain.ts b/packages/worker/src/mcp/capabilities/packages/domain.ts index e51d0fec74..552176004e 100644 --- a/packages/worker/src/mcp/capabilities/packages/domain.ts +++ b/packages/worker/src/mcp/capabilities/packages/domain.ts @@ -16,7 +16,7 @@ import { savePackageCapability } from './save-package.ts' export const packagesDomain = defineDomain({ name: capabilityDomainNames.packages, description: - 'Saved packages are the only top-level persisted primitive. Coding agents with local git access should use package_get_git_remote (create: true for new packages) for clone-edit-push workflows; tool-only agents create with package_save and edit through repo sessions. Package metadata is rooted at package.json, including exports, jobs, apps, services, and event subscriptions.', + 'Saved packages, the only top-level persisted primitive: repo-backed code rooted at package.json whose metadata declares exports, jobs, apps, services, and event subscriptions.', keywords: [ 'package', 'repo', diff --git a/packages/worker/src/mcp/capabilities/secrets/domain.ts b/packages/worker/src/mcp/capabilities/secrets/domain.ts index 83c8169bb2..6a94407182 100644 --- a/packages/worker/src/mcp/capabilities/secrets/domain.ts +++ b/packages/worker/src/mcp/capabilities/secrets/domain.ts @@ -8,7 +8,7 @@ import { secretSetCapability } from './secret-set.ts' export const secretsDomain = defineDomain({ name: capabilityDomainNames.secrets, description: - 'Server-side secret references that can be created, listed, and deleted without placing raw secret values into prompts, execute results, or package app source. Never ask users to paste secrets, tokens, API keys, passwords, or credentials into chat.', + 'Server-side secret references that can be created, listed, and deleted without placing raw secret values into prompts, execute results, or package app source.', keywords: ['secret', 'credentials', 'reference', 'secure input'], capabilities: [ secretListCapability, From e6f250a1a2d450368b2be55488059d48f1c0c9ff Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Fri, 17 Jul 2026 22:38:33 +0000 Subject: [PATCH 3/3] Restore secrets-in-chat prohibition to secrets domain description Co-authored-by: Kent C. Dodds --- packages/worker/src/mcp/capabilities/secrets/domain.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/worker/src/mcp/capabilities/secrets/domain.ts b/packages/worker/src/mcp/capabilities/secrets/domain.ts index 6a94407182..9fb5859f8c 100644 --- a/packages/worker/src/mcp/capabilities/secrets/domain.ts +++ b/packages/worker/src/mcp/capabilities/secrets/domain.ts @@ -8,7 +8,7 @@ import { secretSetCapability } from './secret-set.ts' export const secretsDomain = defineDomain({ name: capabilityDomainNames.secrets, description: - 'Server-side secret references that can be created, listed, and deleted without placing raw secret values into prompts, execute results, or package app source.', + 'Server-side secret references that can be created, listed, and deleted without placing raw secret values into prompts, execute results, or package app source. Never ask users to paste secret values into chat.', keywords: ['secret', 'credentials', 'reference', 'secure input'], capabilities: [ secretListCapability,