Skip to content

Conversation

@ochafik
Copy link
Collaborator

@ochafik ochafik commented Dec 11, 2025

Summary

Fixes #129 - The App class now stores the initial hostContext received during initialization and exposes it via getHostContext().

  • Add _hostContext private property to App class
  • Store result.hostContext in connect() method
  • Add getHostContext() getter method (parallel to getHostCapabilities())
  • Update onhostcontextchanged setter to merge partial updates into stored context
  • Add default notification handler to update context even when user hasn't set onhostcontextchanged

This enables apps to:

  • Access toolInfo immediately after connection (only available in initial context)
  • Render with correct theme/locale without waiting for first notification
  • Synchronously access viewport, timezone, and other initial state

Test plan

  • Added tests for App receives initial hostContext after connect
  • Added tests for getHostContext returns undefined before connect
  • Added tests for getHostContext merges updates from onhostcontextchanged
  • Added tests for getHostContext updates even without user setting onhostcontextchanged
  • Added tests for getHostContext accumulates multiple partial updates
  • All 24 tests pass

🤖 Generated with Claude Code

@pkg-pr-new
Copy link

pkg-pr-new bot commented Dec 11, 2025

Open in StackBlitz

npm i https://pkg.pr.new/modelcontextprotocol/ext-apps/@modelcontextprotocol/ext-apps@139

commit: 5538686

Fixes #129 - The App class now stores the initial hostContext received
during initialization and exposes it via getHostContext().

Changes:
- Add _hostContext private property to App class
- Store result.hostContext in connect() method
- Add getHostContext() getter method (parallel to getHostCapabilities())
- Update onhostcontextchanged setter to merge partial updates into
  stored context
- Add default notification handler to update context even when
  user hasn't set onhostcontextchanged

This enables apps to:
- Access toolInfo immediately after connection (only in initial context)
- Render with correct theme/locale without waiting for first notification
- Synchronously access viewport, timezone, and other initial state

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
@ochafik ochafik force-pushed the ochafik/fix-issue-129-host-context branch from 36aa8a8 to 1a95181 Compare December 11, 2025 22:50
@ochafik ochafik marked this pull request as ready for review December 11, 2025 22:52
@ochafik ochafik requested review from idosal and liady December 11, 2025 22:53
jonathanhefner
jonathanhefner previously approved these changes Dec 11, 2025
Comment on lines 319 to 341
it("getHostContext accumulates multiple partial updates", async () => {
// Need fresh transports for new bridge
const [newAppTransport, newBridgeTransport] =
InMemoryTransport.createLinkedPair();

const initialContext = {
theme: "light" as const,
locale: "en-US",
viewport: { width: 800, height: 600 },
};
const newBridge = new AppBridge(
createMockClient() as Client,
testHostInfo,
testHostCapabilities,
{ hostContext: initialContext },
);
const newApp = new App(testAppInfo, {}, { autoResize: false });

await newBridge.connect(newBridgeTransport);
await newApp.connect(newAppTransport);

// Update only theme
newBridge.setHostContext({ ...initialContext, theme: "dark" });
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I might be misunderstanding, but is this actually testing getHostContext accumulates multiple partial updates? Or should we omit ...initialContext here?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oops good catch, thanks, fixed

Comment on lines 340 to 350
// Update only theme
newBridge.setHostContext({ ...initialContext, theme: "dark" });
await flush();

// Update viewport
newBridge.setHostContext({
theme: "dark",
locale: "en-US",
viewport: { width: 1024, height: 768 },
});
await flush();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why two newBridge.setHostContext() calls?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed to address intent:

      // Send partial update: only theme changes
      newBridge.sendHostContextChange({ theme: "dark" });
      await flush();

      // Send another partial update: only viewport changes
      newBridge.sendHostContextChange({ viewport: { width: 1024, height: 768 } });
      await flush();

      // getHostContext should have accumulated all updates:
      // - locale from initial (unchanged)
      // - theme from first partial update
      // - viewport from second partial update
      const context = newApp.getHostContext();
      expect(context?.theme).toBe("dark");
      expect(context?.locale).toBe("en-US");
      expect(context?.viewport).toEqual({ width: 1024, height: 768 });

Address PR review feedback: The test was using setHostContext with full
context spreads which didn't clearly demonstrate partial update
accumulation. Now uses sendHostContextChange directly to send truly
partial updates (only theme, then only viewport), making it clear
the App correctly merges multiple partial notifications.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
@ochafik ochafik merged commit eaea3f9 into main Dec 11, 2025
8 checks passed
@ochafik ochafik deleted the ochafik/fix-issue-129-host-context branch December 13, 2025 12:09
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.

App class does not store hostContext from initialize response

3 participants