Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions crates/goose-server/src/routes/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ pub mod prompts;
pub mod recipe;
pub mod recipe_utils;
pub mod reply;
pub mod sampling;
pub mod schedule;
pub mod session;
pub mod session_events;
Expand All @@ -35,6 +34,5 @@ pub fn configure(state: Arc<crate::state::AppState>, secret_key: String) -> Rout
.merge(telemetry::routes(state.clone()))
.merge(mcp_app_proxy::routes(secret_key))
.merge(session_events::routes(state.clone()))
.merge(sampling::routes(state.clone()))
.merge(dictation::routes(state.clone()))
}
97 changes: 0 additions & 97 deletions crates/goose-server/src/routes/sampling.rs

This file was deleted.

11 changes: 4 additions & 7 deletions crates/goose/src/goose_apps/cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ use tracing::warn;
use super::app::GooseApp;

static CLOCK_HTML: &str = include_str!("../goose_apps/clock.html");
static CHAT_HTML: &str = include_str!("../goose_apps/chat.html");
const APPS_EXTENSION_NAME: &str = "apps";

pub struct McpAppCache {
Expand All @@ -25,12 +24,10 @@ impl McpAppCache {
}

fn ensure_default_apps(&self) {
for (uri, html) in [("apps://clock", CLOCK_HTML), ("apps://chat", CHAT_HTML)] {
if self.get_app(APPS_EXTENSION_NAME, uri).is_none() {
if let Ok(mut app) = GooseApp::from_html(html) {
app.mcp_servers = vec![APPS_EXTENSION_NAME.to_string()];
let _ = self.store_app(&app);
}
if self.get_app(APPS_EXTENSION_NAME, "apps://clock").is_none() {
if let Ok(mut app) = GooseApp::from_html(CLOCK_HTML) {
app.mcp_servers = vec![APPS_EXTENSION_NAME.to_string()];
let _ = self.store_app(&app);
}
}
}
Expand Down
184 changes: 0 additions & 184 deletions crates/goose/src/goose_apps/chat.html

This file was deleted.

37 changes: 1 addition & 36 deletions ui/desktop/src/components/McpApps/McpAppRenderer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,6 @@ import {
McpAppToolInputPartial,
DimensionLayout,
OnDisplayModeChange,
SamplingCreateMessageParams,
SamplingCreateMessageResponse,
} from './types';
import {
useDisplayMode,
Expand Down Expand Up @@ -676,13 +674,6 @@ export default function McpAppRenderer({

const [containerWidth, setContainerWidth] = useState<number>(0);
const [containerHeight, setContainerHeight] = useState<number>(0);
const [apiHost, setApiHost] = useState<string | null>(null);
const [secretKey, setSecretKey] = useState<string | null>(null);

useEffect(() => {
window.electron.getGoosedHostPort().then(setApiHost);
window.electron.getSecretKey().then(setSecretKey);
}, []);

// Fetch the resource from the extension to get HTML and metadata (CSP, permissions, etc.).
// If cachedHtml is provided we show it immediately; the fetch updates metadata and
Expand Down Expand Up @@ -933,38 +924,12 @@ export default function McpAppRenderer({

const handleFallbackRequest = useCallback(
async (request: JSONRPCRequest, _extra: RequestHandlerExtra) => {
if (request.method === 'sampling/createMessage') {
if (!sessionId || !apiHost || !secretKey) {
throw new Error('Session not initialized for sampling request');
}
const { messages, systemPrompt, maxTokens } =
request.params as unknown as SamplingCreateMessageParams;
const response = await fetch(`${apiHost}/sessions/${sessionId}/sampling/message`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Secret-Key': secretKey,
},
body: JSON.stringify({
messages: messages.map((m) => ({
role: m.role,
content: m.content,
})),
systemPrompt,
maxTokens,
}),
});
if (!response.ok) {
throw new Error(`Sampling request failed: ${response.statusText}`);
}
return (await response.json()) as SamplingCreateMessageResponse;
}
return {
status: 'error' as const,
message: `Unhandled JSON-RPC method: ${request.method ?? '<unknown>'}`,
Comment on lines 925 to 929

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Stop advertising sampling before dropping the app bridge

In desktop sessions, MCP servers still see Goose advertise sampling because GooseClient::get_info still calls .enable_sampling() in crates/goose/src/agents/mcp_client.rs, but MCP app iframes now get an unhandled-method result for sampling/createMessage. For any MCP server that serves a UI app after seeing the sampling capability and has that app request sampling from the host, the app will fail at runtime even though the server was told the capability is available; remove the advertised capability/handler in the MCP client as well, or keep this bridge until both paths are removed.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Since MCP sampling is still supported globally, removing the app iframe bridge creates an inconsistent capability contract. I’ll keep the bridge in this PR and limit the retirement behavior to the built-in Chat app

};
Comment on lines 927 to 930

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Keep the sampling bridge while advertising sampling

Fresh evidence in this revision is that this fallback now always reports sampling/createMessage as unhandled, while GooseClient::get_info still calls .enable_sampling() in crates/goose/src/agents/mcp_client.rs:537 and the MCP client still implements create_message. For an MCP server that sees the sampling capability and serves an app whose iframe calls sampling/createMessage (the retired built-in chat used this path), the app now fails at runtime despite the advertised capability; either keep routing this bridge to the existing sampling handler or stop advertising/removing sampling globally in the same change.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

MCP sampling remains supported for MCP servers, but this PR intentionally does not support sampling from MCP app iframes. The app bridge does not advertise sampling in its host capabilities, and the retired built-in Chat app is now blocked because it depended on that unsupported iframe path. We are not removing global MCP sampling, so .enable_sampling() should remain.

},
[sessionId, apiHost, secretKey]
[]
);

const handleError = useCallback((err: Error) => {
Expand Down
Loading
Loading