diff --git a/tools/server/webui/src/lib/components/app/index.ts b/tools/server/webui/src/lib/components/app/index.ts
index 9586d68a17..617daf17b0 100644
--- a/tools/server/webui/src/lib/components/app/index.ts
+++ b/tools/server/webui/src/lib/components/app/index.ts
@@ -27,6 +27,7 @@ export { default as CollapsibleContentBlock } from './chat/ChatMessages/Collapsi
export { default as MessageBranchingControls } from './chat/ChatMessages/ChatMessageBranchingControls.svelte';
export { default as ChatScreen } from './chat/ChatScreen/ChatScreen.svelte';
+export { default as KeyValuePairs } from './misc/KeyValuePairs.svelte';
export { default as ChatScreenHeader } from './chat/ChatScreen/ChatScreenHeader.svelte';
export { default as ChatScreenProcessingInfo } from './chat/ChatScreen/ChatScreenProcessingInfo.svelte';
diff --git a/tools/server/webui/src/lib/components/app/mcp/McpServerForm.svelte b/tools/server/webui/src/lib/components/app/mcp/McpServerForm.svelte
index 9a39d6dfe6..9fba6702dc 100644
--- a/tools/server/webui/src/lib/components/app/mcp/McpServerForm.svelte
+++ b/tools/server/webui/src/lib/components/app/mcp/McpServerForm.svelte
@@ -1,8 +1,8 @@
@@ -70,55 +50,14 @@
{/if}
-
-
-
- Custom Headers (optional)
-
-
-
-
- {#if headerPairs.length > 0}
-
- {#each headerPairs as pair, index (index)}
-
- updatePairKey(index, e.currentTarget.value)}
- class="flex-1"
- />
-
-
-
- {/each}
-
- {:else}
-
No custom headers configured.
- {/if}
-
+
diff --git a/tools/server/webui/src/lib/components/app/misc/KeyValuePairs.svelte b/tools/server/webui/src/lib/components/app/misc/KeyValuePairs.svelte
new file mode 100644
index 0000000000..586b51edc2
--- /dev/null
+++ b/tools/server/webui/src/lib/components/app/misc/KeyValuePairs.svelte
@@ -0,0 +1,105 @@
+
+
+
+
+ {#if sectionLabel}
+
+ {sectionLabel}
+ {#if sectionLabelOptional}
+ (optional)
+ {/if}
+
+ {/if}
+
+
+
+ {#if pairs.length > 0}
+
+ {#each pairs as pair, index (index)}
+
+ updatePairKey(index, e.currentTarget.value)}
+ class="flex-1"
+ />
+
+
+
+ {/each}
+
+ {:else}
+
{emptyMessage}
+ {/if}
+
diff --git a/tools/server/webui/src/lib/types/common.d.ts b/tools/server/webui/src/lib/types/common.d.ts
new file mode 100644
index 0000000000..e63716b773
--- /dev/null
+++ b/tools/server/webui/src/lib/types/common.d.ts
@@ -0,0 +1,12 @@
+/**
+ * Common utility types used across the application
+ */
+
+/**
+ * Represents a key-value pair.
+ * Used for headers, environment variables, query parameters, etc.
+ */
+export interface KeyValuePair {
+ key: string;
+ value: string;
+}
diff --git a/tools/server/webui/src/lib/types/index.ts b/tools/server/webui/src/lib/types/index.ts
index 7c58015cd1..9b9e6e0cbd 100644
--- a/tools/server/webui/src/lib/types/index.ts
+++ b/tools/server/webui/src/lib/types/index.ts
@@ -66,3 +66,6 @@ export type {
SettingsChatServiceOptions,
SettingsConfigType
} from './settings';
+
+// Common types
+export type { KeyValuePair } from './common';
diff --git a/tools/server/webui/src/lib/utils/mcp.ts b/tools/server/webui/src/lib/utils/mcp.ts
index 5a579ec711..0b2059885d 100644
--- a/tools/server/webui/src/lib/utils/mcp.ts
+++ b/tools/server/webui/src/lib/utils/mcp.ts
@@ -9,11 +9,6 @@ import type { McpServerOverride } from '$lib/types/database';
import { DEFAULT_MCP_CONFIG } from '$lib/constants/mcp';
import { normalizePositiveNumber } from '$lib/utils/number';
-/**
- * Represents a key-value pair for HTTP headers.
- */
-export type HeaderPair = { key: string; value: string };
-
/**
* Detects the MCP transport type from a URL.
* WebSocket URLs (ws:// or wss://) use 'websocket', others use 'streamable_http'.
@@ -84,7 +79,7 @@ export function getFaviconUrl(serverUrl: string): string | null {
* Parses a JSON string of headers into an array of key-value pairs.
* Returns empty array if the JSON is invalid or empty.
*/
-export function parseHeadersToArray(headersJson: string): HeaderPair[] {
+export function parseHeadersToArray(headersJson: string): { key: string; value: string }[] {
if (!headersJson?.trim()) return [];
try {
@@ -106,7 +101,7 @@ export function parseHeadersToArray(headersJson: string): HeaderPair[] {
* Serializes an array of header key-value pairs to a JSON string.
* Filters out pairs with empty keys and returns empty string if no valid pairs.
*/
-export function serializeHeaders(pairs: HeaderPair[]): string {
+export function serializeHeaders(pairs: { key: string; value: string }[]): string {
const validPairs = pairs.filter((p) => p.key.trim());
if (validPairs.length === 0) return '';