Skip to content

Batch toolkit policy resolution to bound MCP connect time#1157

Merged
RhysSullivan merged 1 commit into
mainfrom
toolkit-init-policy-n1
Jun 27, 2026
Merged

Batch toolkit policy resolution to bound MCP connect time#1157
RhysSullivan merged 1 commit into
mainfrom
toolkit-init-policy-n1

Conversation

@RhysSullivan

Copy link
Copy Markdown
Owner

Toolkit MCP endpoints resolved tool policy once per tool over the whole catalog while building the execute-tool description. That N+1 scaled with total catalog size, so large workspaces pushed a toolkit connect past the MCP client connect timeout.

prepare() lets the provider fetch policies and connections once per operation and reuse a pure per-tool resolver; the executor prefers it and falls back to the existing paths. Resolution semantics are unchanged.

Real OpenCode connecting to a toolkit over an 11-source, ~3.3k-tool catalog (post-fix):

OpenCode connects to a large-catalog toolkit

Tests: e2e/cloud/toolkit-policy-perf.test.ts bounds the connect cost (pre-fix ~28s of extra connect time, post-fix sub-second), and e2e/cloud/toolkit-opencode-real.test.ts drives the real OpenCode binary through OAuth.

Toolkit MCP endpoints resolved tool policy once per tool while building
the execute-tool description (connections.list walks the whole catalog).
That is an N+1 of two uncached storage reads per tool, scaling with total
catalog size rather than toolkit size, so a workspace with thousands of
tools pushed a toolkit connect past the MCP client's connect timeout.

Add an optional prepare() to ToolPolicyProvider: core calls it once per
operation to fetch policies and connections in a single pass, then reuses
a pure per-tool resolver for the rest of that operation. The toolkit
provider implements it; the executor prefers it via a "prepared" rule-set
variant and falls back to the existing resolve/list paths. Scope is
per-operation (not memoized on the session-scoped provider) so policy
state stays fresh. Resolution semantics are unchanged: connectivity
gating, per-tool plugin default, and the org personal-dynamic block are
all preserved.

e2e coverage:
- cloud/toolkit-policy-perf.test.ts seeds a production-shaped catalog
  (one real spec plus synthetic sources, ~2,200 tools across 11 sources)
  and asserts a toolkit connect adds only a bounded cost over a
  near-empty control. Pre-fix that delta is ~28s; post-fix it is
  sub-second.
- cloud/toolkit-opencode-real.test.ts drives the real OpenCode binary
  through OAuth against a large-catalog toolkit and asserts it connects.
- scenarios/support/large-catalog.ts is the shared seeding helper.
- src/clients/opencode.ts also shims xdg-open so the browser-open hop is
  captured on Linux, not only macOS.
@greptile-apps

greptile-apps Bot commented Jun 27, 2026

Copy link
Copy Markdown

Greptile Summary

This PR batches toolkit policy lookup during MCP operations. The main changes are:

  • Adds an optional per-operation prepare() resolver to policy providers.
  • Uses the prepared resolver from executor policy checks when available.
  • Adds toolkit support for fetching policies and connections once per operation.
  • Adds large-catalog cloud e2e coverage for toolkit MCP connect time.
  • Adds real OpenCode OAuth and MCP connect coverage.
  • Expands OpenCode opener shims for Linux browser opener commands.

Confidence Score: 5/5

This looks safe to merge.

  • No blocking issues found in the changed code.

Important Files Changed

Filename Overview
packages/core/sdk/src/plugin.ts Adds the optional ToolPolicyProvider.prepare() contract for batched per-operation policy resolution.
packages/core/sdk/src/executor.ts Prefers prepared policy resolvers when present and keeps the existing provider and global-policy fallback paths.
packages/plugins/toolkits/src/server.ts Adds toolkit prepared policy resolution by snapshotting toolkit policies and connections once per operation.
e2e/scenarios/support/large-catalog.ts Adds shared helpers for creating and cleaning up large public-API catalog fixtures.
e2e/cloud/toolkit-policy-perf.test.ts Adds cloud coverage that bounds toolkit MCP connect overhead for large catalogs.
e2e/cloud/toolkit-opencode-real.test.ts Adds real OpenCode coverage for OAuth and toolkit MCP connection against a large catalog.
e2e/src/clients/opencode.ts Adds Linux opener command shims so OpenCode OAuth URL capture works outside macOS.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
  A[tools/list or tools/call] --> B[listActivePolicyRuleSet]
  B --> C{policy provider present}
  C -->|no| D[load global policy rows]
  C -->|prepare exists| E[prepare once per operation]
  C -->|resolve only| F[resolve per tool]
  C -->|list only| G[list rules once]
  E --> H[pure per-tool resolver]
  F --> I[effective policy]
  G --> I
  D --> I
  H --> I
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
  A[tools/list or tools/call] --> B[listActivePolicyRuleSet]
  B --> C{policy provider present}
  C -->|no| D[load global policy rows]
  C -->|prepare exists| E[prepare once per operation]
  C -->|resolve only| F[resolve per tool]
  C -->|list only| G[list rules once]
  E --> H[pure per-tool resolver]
  F --> I[effective policy]
  G --> I
  D --> I
  H --> I
Loading

Reviews (1): Last reviewed commit: "Batch toolkit policy resolution to bound..." | Re-trigger Greptile

@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
executor-marketing 60b6cc1 Commit Preview URL

Branch Preview URL
Jun 27 2026, 06:24 AM

@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Updated (UTC)
✅ Deployment successful!
View logs
executor-cloud 60b6cc1 Jun 27 2026, 06:25 AM

@github-actions

github-actions Bot commented Jun 27, 2026

Copy link
Copy Markdown
Contributor

Cloudflare preview

Torn down — the PR is closed.

@pkg-pr-new

pkg-pr-new Bot commented Jun 27, 2026

Copy link
Copy Markdown

Open in StackBlitz

@executor-js/cli

npm i https://pkg.pr.new/@executor-js/cli@1157

@executor-js/config

npm i https://pkg.pr.new/@executor-js/config@1157

@executor-js/execution

npm i https://pkg.pr.new/@executor-js/execution@1157

@executor-js/sdk

npm i https://pkg.pr.new/@executor-js/sdk@1157

@executor-js/codemode-core

npm i https://pkg.pr.new/@executor-js/codemode-core@1157

@executor-js/runtime-quickjs

npm i https://pkg.pr.new/@executor-js/runtime-quickjs@1157

@executor-js/plugin-file-secrets

npm i https://pkg.pr.new/@executor-js/plugin-file-secrets@1157

@executor-js/plugin-graphql

npm i https://pkg.pr.new/@executor-js/plugin-graphql@1157

@executor-js/plugin-keychain

npm i https://pkg.pr.new/@executor-js/plugin-keychain@1157

@executor-js/plugin-mcp

npm i https://pkg.pr.new/@executor-js/plugin-mcp@1157

@executor-js/plugin-onepassword

npm i https://pkg.pr.new/@executor-js/plugin-onepassword@1157

@executor-js/plugin-openapi

npm i https://pkg.pr.new/@executor-js/plugin-openapi@1157

executor

npm i https://pkg.pr.new/executor@1157

commit: 60b6cc1

@RhysSullivan RhysSullivan merged commit e4adb56 into main Jun 27, 2026
15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant