diff --git a/cli/package.json b/cli/package.json
index bfb173a8..7ace0392 100644
--- a/cli/package.json
+++ b/cli/package.json
@@ -1,6 +1,6 @@
{
"name": "@modelcontextprotocol/inspector-cli",
- "version": "0.15.0",
+ "version": "0.16.0",
"description": "CLI for the Model Context Protocol inspector",
"license": "MIT",
"author": "Anthropic, PBC (https://anthropic.com)",
diff --git a/client/package.json b/client/package.json
index 59bf2288..2d0cc50b 100644
--- a/client/package.json
+++ b/client/package.json
@@ -1,6 +1,6 @@
{
"name": "@modelcontextprotocol/inspector-client",
- "version": "0.15.0",
+ "version": "0.16.0",
"description": "Client-side application for the Model Context Protocol inspector",
"license": "MIT",
"author": "Anthropic, PBC (https://anthropic.com)",
diff --git a/client/src/components/__tests__/DynamicJsonForm.test.tsx b/client/src/components/__tests__/DynamicJsonForm.test.tsx
index afd435d7..cd321418 100644
--- a/client/src/components/__tests__/DynamicJsonForm.test.tsx
+++ b/client/src/components/__tests__/DynamicJsonForm.test.tsx
@@ -117,8 +117,11 @@ describe("DynamicJsonForm Complex Fields", () => {
const input = screen.getByRole("textbox");
expect(input).toHaveProperty("type", "textarea");
const buttons = screen.getAllByRole("button");
- expect(buttons).toHaveLength(1);
- expect(buttons[0]).toHaveProperty("textContent", "Format JSON");
+ expect(buttons).toHaveLength(2); // Copy JSON + Format JSON
+ const copyButton = screen.getByRole("button", { name: /copy json/i });
+ const formatButton = screen.getByRole("button", { name: /format json/i });
+ expect(copyButton).toBeTruthy();
+ expect(formatButton).toBeTruthy();
});
it("should pass changed values to onChange", () => {
@@ -137,3 +140,72 @@ describe("DynamicJsonForm Complex Fields", () => {
});
});
});
+
+describe("DynamicJsonForm Copy JSON Functionality", () => {
+ const mockWriteText = jest.fn(() => Promise.resolve());
+
+ beforeEach(() => {
+ jest.clearAllMocks();
+ Object.assign(navigator, {
+ clipboard: {
+ writeText: mockWriteText,
+ },
+ });
+ });
+
+ const renderFormInJsonMode = (props = {}) => {
+ const defaultProps = {
+ schema: {
+ type: "object",
+ properties: {
+ nested: { oneOf: [{ type: "string" }, { type: "integer" }] },
+ },
+ } as unknown as JsonSchemaType,
+ value: { nested: "test value" },
+ onChange: jest.fn(),
+ };
+ return render();
+ };
+
+ describe("Copy JSON Button", () => {
+ it("should render Copy JSON button when in JSON mode", () => {
+ renderFormInJsonMode();
+
+ const copyButton = screen.getByRole("button", { name: "Copy JSON" });
+ expect(copyButton).toBeTruthy();
+ });
+
+ it("should not render Copy JSON button when not in JSON mode", () => {
+ const simpleSchema = {
+ type: "string" as const,
+ description: "Test string field",
+ };
+
+ render(
+ ,
+ );
+
+ const copyButton = screen.queryByRole("button", { name: "Copy JSON" });
+ expect(copyButton).toBeNull();
+ });
+
+ it("should copy JSON to clipboard when clicked", async () => {
+ const testValue = { nested: "test value", number: 42 };
+
+ renderFormInJsonMode({ value: testValue });
+
+ const copyButton = screen.getByRole("button", { name: "Copy JSON" });
+ fireEvent.click(copyButton);
+
+ await waitFor(() => {
+ expect(mockWriteText).toHaveBeenCalledWith(
+ JSON.stringify(testValue, null, 2),
+ );
+ });
+ });
+ });
+});
diff --git a/package-lock.json b/package-lock.json
index 075b0a28..fafcb5f7 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "@modelcontextprotocol/inspector",
- "version": "0.15.0",
+ "version": "0.16.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@modelcontextprotocol/inspector",
- "version": "0.15.0",
+ "version": "0.16.0",
"license": "MIT",
"workspaces": [
"client",
@@ -14,9 +14,9 @@
"cli"
],
"dependencies": {
- "@modelcontextprotocol/inspector-cli": "^0.15.0",
- "@modelcontextprotocol/inspector-client": "^0.15.0",
- "@modelcontextprotocol/inspector-server": "^0.15.0",
+ "@modelcontextprotocol/inspector-cli": "^0.16.0",
+ "@modelcontextprotocol/inspector-client": "^0.16.0",
+ "@modelcontextprotocol/inspector-server": "^0.16.0",
"@modelcontextprotocol/sdk": "^1.13.1",
"concurrently": "^9.0.1",
"open": "^10.1.0",
@@ -44,7 +44,7 @@
},
"cli": {
"name": "@modelcontextprotocol/inspector-cli",
- "version": "0.15.0",
+ "version": "0.16.0",
"license": "MIT",
"dependencies": {
"@modelcontextprotocol/sdk": "^1.13.1",
@@ -67,7 +67,7 @@
},
"client": {
"name": "@modelcontextprotocol/inspector-client",
- "version": "0.15.0",
+ "version": "0.16.0",
"license": "MIT",
"dependencies": {
"@modelcontextprotocol/sdk": "^1.13.1",
@@ -10987,7 +10987,7 @@
},
"server": {
"name": "@modelcontextprotocol/inspector-server",
- "version": "0.15.0",
+ "version": "0.16.0",
"license": "MIT",
"dependencies": {
"@modelcontextprotocol/sdk": "^1.13.1",
diff --git a/package.json b/package.json
index 5d5fe52f..6962f4a7 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@modelcontextprotocol/inspector",
- "version": "0.15.0",
+ "version": "0.16.0",
"description": "Model Context Protocol inspector",
"license": "MIT",
"author": "Anthropic, PBC (https://anthropic.com)",
@@ -44,9 +44,9 @@
"check-version": "node scripts/check-version-consistency.js"
},
"dependencies": {
- "@modelcontextprotocol/inspector-cli": "^0.15.0",
- "@modelcontextprotocol/inspector-client": "^0.15.0",
- "@modelcontextprotocol/inspector-server": "^0.15.0",
+ "@modelcontextprotocol/inspector-cli": "^0.16.0",
+ "@modelcontextprotocol/inspector-client": "^0.16.0",
+ "@modelcontextprotocol/inspector-server": "^0.16.0",
"@modelcontextprotocol/sdk": "^1.13.1",
"concurrently": "^9.0.1",
"open": "^10.1.0",
diff --git a/server/package.json b/server/package.json
index b43fc289..a0c54cd3 100644
--- a/server/package.json
+++ b/server/package.json
@@ -1,6 +1,6 @@
{
"name": "@modelcontextprotocol/inspector-server",
- "version": "0.15.0",
+ "version": "0.16.0",
"description": "Server-side application for the Model Context Protocol inspector",
"license": "MIT",
"author": "Anthropic, PBC (https://anthropic.com)",