Skip to content
Draft
Show file tree
Hide file tree
Changes from all 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
62 changes: 62 additions & 0 deletions client/e2e/resource-refresh.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { test, expect } from "@playwright/test";

const AUTH_TOKEN = process.env.MCP_PROXY_AUTH_TOKEN ?? "";
const APP_URL = AUTH_TOKEN
? `http://localhost:6274/?MCP_PROXY_AUTH_TOKEN=${AUTH_TOKEN}`
: "http://localhost:6274/";

test.describe("Resource Refresh Button", () => {
test.beforeEach(async ({ page }) => {
await page.goto(APP_URL);

// Set up STDIO transport with server-everything
const transportSelect = page.getByLabel("Transport Type");
await expect(transportSelect).toBeVisible();
await expect(transportSelect).toContainText("STDIO");

const commandInput = page.locator("#command-input");
await commandInput.fill("npx");

const argsInput = page.locator("#arguments-input");
await argsInput.fill("-y @modelcontextprotocol/server-everything@latest");

// Connect
await page.getByRole("button", { name: "Connect" }).click();

// Wait for connection to be established
await expect(page.getByRole("button", { name: "Disconnect" })).toBeVisible({
timeout: 30000,
});
});

test("should re-fetch resource when refresh button is clicked", async ({
page,
}) => {
// Navigate to Resources tab
await page.getByRole("tab", { name: "Resources" }).click();

// List resources
await page.getByRole("button", { name: "List Resources" }).click();

// Wait for a resource to appear and click it
const firstResource = page.getByText("architecture.md").first();
await expect(firstResource).toBeVisible({ timeout: 10000 });
await firstResource.click();

// Wait for resource content to load
await page.waitForTimeout(2000);

// Count current resources/read entries in history
const historyEntries = page.locator("text=resources/read");
const initialCount = await historyEntries.count();
expect(initialCount).toBeGreaterThanOrEqual(1);

// Click the Refresh button
await page.getByRole("button", { name: "Refresh" }).click();

// Verify a new resources/read request appeared in history
await expect(historyEntries).toHaveCount(initialCount + 1, {
timeout: 10000,
});
});
});
13 changes: 9 additions & 4 deletions client/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -893,8 +893,13 @@ const App = () => {
setPromptContent(JSON.stringify(response, null, 2));
};

const readResource = async (uri: string) => {
if (fetchingResources.has(uri) || resourceContentMap[uri]) {
const readResource = async (uri: string, force: boolean = false) => {
if (fetchingResources.has(uri)) {
return;
}

if (!force && resourceContentMap[uri]) {
setResourceContent(resourceContentMap[uri]);
return;
}

Expand Down Expand Up @@ -1471,9 +1476,9 @@ const App = () => {
setResourceTemplates([]);
setNextResourceTemplateCursor(undefined);
}}
readResource={(uri) => {
readResource={(uri, force) => {
clearError("resources");
readResource(uri);
readResource(uri, force);
}}
selectedResource={selectedResource}
setSelectedResource={(resource) => {
Expand Down
4 changes: 2 additions & 2 deletions client/src/components/ResourcesTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ const ResourcesTab = ({
clearResources: () => void;
listResourceTemplates: () => void;
clearResourceTemplates: () => void;
readResource: (uri: string) => void;
readResource: (uri: string, force?: boolean) => void;
selectedResource: Resource | null;
setSelectedResource: (resource: Resource | null) => void;
handleCompletion: (
Expand Down Expand Up @@ -229,7 +229,7 @@ const ResourcesTab = ({
<Button
variant="outline"
size="sm"
onClick={() => readResource(selectedResource.uri)}
onClick={() => readResource(selectedResource.uri, true)}
>
<RefreshCw className="w-4 h-4 mr-2" />
Refresh
Expand Down
Loading