Skip to content

MCP server lock (mcpServerLock) also blocks the approved package when its export is called from execute #2791

Description

@justin-thurman

I'm Claude (an AI agent), filing this on behalf of @justin-thurman, who asked me to report it.

Summary

After mcpServerLock limits an MCP server to a package, that package can't call the server when an agent invokes its export from execute. The package is denied the same way ad hoc execute code is. As far as I can tell, the documented loop in guide:locked_mcp_server can't work for the main way agents call packages.

Steps to reproduce

  1. mcpServerAdd({ name: 'notion', url: 'https://mcp.notion.com/mcp' }), then authorize. mcpServerList shows state: "ready", 44 tools.
  2. Publish a thin wrapper package (@justin-thurman/notion-read) whose exports call kody.mcp["notion"].notion_search_<hash>(...) and similar. From execute, import smokeTest from 'kody:@justin-thurman/notion-read/smoke-test' works.
  3. mcpServerLock({ server: 'notion', package_id: '<notion-read package id>' }). mcpServerList now shows usageMode: "packages" and allowedPackageIds: ["<notion-read package id>"].
  4. From execute, call the same export again, as the guide's step 5 says ("Smoke-test from the package, not execute").

Expected

The package export succeeds. A direct kody.mcp["notion"] call from execute fails with the account URL.

Actual

Both fail with:

Unknown MCP server "notion". Available MCP servers: none.

Same result with:

  • a static import: import x from 'kody:@scope/pkg/export'
  • a computed import: await import('kody:@scope/pkg/export')
  • a republish of the package after the lock (new published_commit)

Switching Usage back to "any context" on the website fixes it right away.

Likely cause

assertCanUseMcpServer / filterEnabledMcpServerRefsForCaller (packages/worker/src/mcp-client/package-access.ts) allow a call only when it has a packageId. mcp-server/index.ts reads that from ctx.callerContext.storageContext?.packageId. Package code imported into an execute module seems to run with execute's caller context, so packageId is empty and the server is filtered out. Package-run surfaces such as jobs, webhooks, and apps may work. I didn't test them.

A smaller related problem: since the server is filtered out of the listing before the assert runs, execute gets Unknown MCP server rather than the friendlier createMcpServerExecuteAccessDeniedMessage text with the usage URL that the guide describes.

The same pattern probably affects integrationLock (integrations/package-access.ts looks similar) and so the locked_gmail_drafts loop, but I haven't verified that.

Separate: @kody/notion-mcp can't find any Notion tools

@kody/notion-mcp (src/mcp.ts callNotionMcp) looks up tools by bare names (search, notion-search, API-post-search). Connected servers expose tools as <snake_name>_<8-hex hash>, e.g. notion_search_9cd52b13. kody.mcp["notion"]["notion-search"] throws Unknown MCP tool "notion-search", so the package's search and smoke-test can't find a tool even with a working connection. (guide:provider_notion doesn't mention the MCP lane at all, although that package's README calls it the preferred one-click path.)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions