# TUUI MCP Architecture: How Tools, Prompts, and Resources Are Handled

> Explore the TUUI MCP architecture for managing tools, prompts, and resources. Discover TUUI's three-layer system for uniform handling across MCP servers.

- Repository: [AIQL/tuui](https://github.com/ai-ql/tuui)
- Tags: architecture
- Published: 2026-02-23

---

**TUUI implements a three-layer architecture—type definitions, runtime store, and feature stores—to uniformly handle MCP tools, prompts, and resources across any number of Model Context Protocol servers.**

The Model Context Protocol (MCP) integration in TUUI (ai-ql/tuui) provides a type-safe abstraction for discovering and invoking remote capabilities. This architecture for handling MCP tools, prompts, and resources within TUUI separates concerns into distinct layers: static type contracts, dynamic runtime management, and UI-specific feature consumption.

## The Three-Layer Architecture Overview

TUUI's MCP stack is organized into three cooperating layers that transform raw server capabilities into rendered UI elements:

| Layer | Responsibility | Core Implementation |
|-------|----------------|----------------------|
| **Type definitions** | Mirrors the MCP SDK signatures into TypeScript contracts | [`src/types/mcp.d.ts`](https://github.com/ai-ql/tuui/blob/main/src/types/mcp.d.ts) |
| **Runtime store** | Discovers servers, merges Stdio metadata, and exposes generic invocation helpers | [`src/renderer/store/mcp.ts`](https://github.com/ai-ql/tuui/blob/main/src/renderer/store/mcp.ts) |
| **Feature stores** | Consumes the generic API to fetch prompts, list tools, or read resources | [`src/renderer/store/prompt.ts`](https://github.com/ai-ql/tuui/blob/main/src/renderer/store/prompt.ts) (and inline resource handling in [`mcp.ts`](https://github.com/ai-ql/tuui/blob/main/mcp.ts)) |

## Type Definitions Layer

The foundation resides in **[`src/types/mcp.d.ts`](https://github.com/ai-ql/tuui/blob/main/src/types/mcp.d.ts)**, which re-exports simplified, UI-friendly versions of the official MCP SDK types:

- **`McpObject`** – Defines the optional `metadata`, `tools`, `prompts`, and `resources` fields.
- **`ToolType`** – Specifies the OpenAI-style function call shape (`name`, `description`, `parameters`).
- **`MCPAPI`** – A `Record<string, McpObject>` map where keys represent server names.

These declarations guarantee that every subsequent layer respects the MCP contract without importing heavy SDK dependencies into the renderer process.

## Runtime Store Layer

**[`src/renderer/store/mcp.ts`](https://github.com/ai-ql/tuui/blob/main/src/renderer/store/mcp.ts)** implements the central Pinia store (`useMcpStore`) that bridges the main-process MCP client with the UI.

### Server Discovery and Merging

The store initializes by calling `getRawServers()`, which reads the `window.mcpServers` object exposed by the preload script ([`src/preload/index.ts`](https://github.com/ai-ql/tuui/blob/main/src/preload/index.ts)). It then merges these with locally-run Stdio servers via `useStdioStore()`, normalizing them into a unified `MCPAPI` map.

The `getAllowedPrimitive(item)` helper inspects each server to determine which primitives (`tools`, `resources`, `prompts`) it implements, enabling dynamic UI filtering.

### Dynamic Invocation Helpers

The store provides type-safe methods for runtime interaction:

- **`getServerFunction({serverName, primitiveName, methodName})`** – Dynamically resolves methods like `servers[mySrv].tools.list`.
- **`listServerTools()`** – Aggregates available tools into an array of `FunctionType` objects ready for OpenAI-style function calling.
- **`callTool(name, args)`** – Resolves a tool via `getTool`, then invokes `tools.call` with JSON-encoded arguments.
- **`getAllByServer()`** – Returns all primitives grouped by server name for bulk operations.

The `watchServerUpdate` watcher keeps reactive UI checklists synchronized when servers connect or disconnect.

## Feature Store Layer

Specialized stores consume the generic MCP API for specific UI features. **[`src/renderer/store/prompt.ts`](https://github.com/ai-ql/tuui/blob/main/src/renderer/store/prompt.ts)** demonstrates this pattern:

- **`fetchPrompts()`** – Uses `useMcpStore().getSelected` to identify the active server, then calls its `prompts.list` method.
- **`fetchAllPrompts()`** – Iterates over all servers from `getServers()` and aggregates prompt lists.
- **`fetchSelect(params)`** – Constructs a `GetPromptRequest`, invokes the server's `prompts.get`, and converts the resulting `ChatCompletionPromptMessage` into the UI's internal `ChatCompletionRequestContent` via `mcpStore.convertItem`.

This architecture ensures that feature stores remain agnostic of underlying RPC shapes, relying solely on the standardized interface exposed by the MCP store.

## Key Implementation Files

| File | Role | Link |
|------|------|------|
| [`src/types/mcp.d.ts`](https://github.com/ai-ql/tuui/blob/main/src/types/mcp.d.ts) | Central type contract for MCP objects, tools, prompts, resources. | [view](https://github.com/ai-ql/tuui/blob/main/src/types/mcp.d.ts) |
| [`src/renderer/store/mcp.ts`](https://github.com/ai-ql/tuui/blob/main/src/renderer/store/mcp.ts) | Pinia store that discovers MCP servers, merges Stdio metadata, and provides generic helpers (`listServerTools`, `callTool`, `getServerFunction`). | [view](https://github.com/ai-ql/tuui/blob/main/src/renderer/store/mcp.ts) |
| [`src/renderer/store/prompt.ts`](https://github.com/ai-ql/tuui/blob/main/src/renderer/store/prompt.ts) | Feature store that uses `useMcpStore` to list, fetch, and render prompts. | [view](https://github.com/ai-ql/tuui/blob/main/src/renderer/store/prompt.ts) |
| [`src/main/mcp/client.ts`](https://github.com/ai-ql/tuui/blob/main/src/main/mcp/client.ts) | Implements the preload-side `window.mcpServers` client that talks to the MCP server (creates the `MCPAPI` map). | [view](https://github.com/ai-ql/tuui/blob/main/src/main/mcp/client.ts) |
| [`src/preload/index.ts`](https://github.com/ai-ql/tuui/blob/main/src/preload/index.ts) | Exposes the MCP client (`window.mcpServers`) and the DXT manifest to the renderer. | [view](https://github.com/ai-ql/tuui/blob/main/src/preload/index.ts) |
| [`src/main/mcp/connection.ts`](https://github.com/ai-ql/tuui/blob/main/src/main/mcp/connection.ts) & [`src/main/mcp/config.ts`](https://github.com/ai-ql/tuui/blob/main/src/main/mcp/config.ts) | Handle low-level connection lifecycle and configuration parsing for MCP servers. | [connection](https://github.com/ai-ql/tuui/blob/main/src/main/mcp/connection.ts), [config](https://github.com/ai-ql/tuui/blob/main/src/main/mcp/config.ts) |

## Code Examples

### List All Available Tools from the Current Server

```typescript
import { useMcpStore } from '@/renderer/store/mcp'

async function showTools() {
  const store = useMcpStore()
  const tools = await store.listServerTools()   // ← uses getServerFunction → tools.list
  console.table(tools.map(t => t.function))
}
showTools()

```

*Source:* `listServerTools` in [[`src/renderer/store/mcp.ts`](https://github.com/ai-ql/tuui/blob/main/src/renderer/store/mcp.ts)](https://github.com/ai-ql/tuui/blob/main/src/renderer/store/mcp.ts).

### Call a Tool with JSON Arguments

```typescript
import { useMcpStore } from '@/renderer/store/mcp'

async function runTool(name: string, args: Record<string, unknown>) {
  const store = useMcpStore()
  const result = await store.callTool(name, JSON.stringify(args))
  console.log('Tool response →', result)
}
runTool('search_web', { query: 'latest AI research' })

```

*Source:* `callTool` in [[`src/renderer/store/mcp.ts`](https://github.com/ai-ql/tuui/blob/main/src/renderer/store/mcp.ts)](https://github.com/ai-ql/tuui/blob/main/src/renderer/store/mcp.ts).

### Load All Prompts Across Every MCP Server

```typescript
import { getServers } from '@/renderer/store/mcp'

async function loadAllPrompts() {
  const promptStore = await import('@/renderer/store/prompt') // lazy load
  const all = await promptStore.usePromptStore().fetchAllPrompts()
  console.log(`Fetched ${all.length} prompts from ${Object.keys(getServers()!).length} servers`)
}
loadAllPrompts()

```

*Source:* `fetchAllPrompts` in [[`src/renderer/store/prompt.ts`](https://github.com/ai-ql/tuui/blob/main/src/renderer/store/prompt.ts)](https://github.com/ai-ql/tuui/blob/main/src/renderer/store/prompt.ts).

### Read a Resource from a Specific Server

```typescript
import { getServers } from '@/renderer/store/mcp'

async function readResource(server: string, id: string) {
  const servers = getServers()
  const read = servers?.[server]?.resources?.read
  if (typeof read === 'function') {
    const res = await read({ method: 'resources/read', params: { name: id } })
    console.log('Resource data →', res.resource)
  }
}
readResource('my-mcp', 'config.yaml')

```

*Pattern* follows the same dynamic lookup used in `callTool`.

## Summary

- **Three-layer design**: Type definitions ([`mcp.d.ts`](https://github.com/ai-ql/tuui/blob/main/mcp.d.ts)), runtime store ([`mcp.ts`](https://github.com/ai-ql/tuui/blob/main/mcp.ts)), and feature stores ([`prompt.ts`](https://github.com/ai-ql/tuui/blob/main/prompt.ts)) create a clean separation between protocol contracts, server management, and UI consumption.
- **Dynamic discovery**: The `useMcpStore` automatically merges remote MCP servers with local Stdio processes, normalizing them into a unified `MCPAPI` map.
- **Generic invocation**: Helper methods like `getServerFunction`, `callTool`, and `listServerTools` allow UI components to invoke any MCP primitive without knowing the underlying RPC shape.
- **Type safety**: The `McpObject`, `ToolType`, and `MCPAPI` interfaces ensure that tools, prompts, and resources are handled consistently across the renderer and main processes.

## Frequently Asked Questions

### How does TUUI discover available MCP servers at runtime?

TUUI discovers servers through the `getRawServers()` method in [`src/renderer/store/mcp.ts`](https://github.com/ai-ql/tuui/blob/main/src/renderer/store/mcp.ts), which reads the `window.mcpServers` object exposed by the preload script. This object is populated by [`src/main/mcp/client.ts`](https://github.com/ai-ql/tuui/blob/main/src/main/mcp/client.ts) and merged with local Stdio server metadata from `useStdioStore()`, creating a unified registry of all available MCP capabilities.

### What is the difference between the MCP store and the Prompt store?

The **MCP store** ([`src/renderer/store/mcp.ts`](https://github.com/ai-ql/tuui/blob/main/src/renderer/store/mcp.ts)) is a generic runtime layer that handles server discovery, connection management, and dynamic invocation of any MCP primitive (tools, prompts, or resources). The **Prompt store** ([`src/renderer/store/prompt.ts`](https://github.com/ai-ql/tuui/blob/main/src/renderer/store/prompt.ts)) is a feature-specific consumer that uses the MCP store's generic API to implement UI-focused operations like `fetchAllPrompts` or `fetchSelect`, converting raw MCP responses into chat-compatible message formats.

### How does TUUI handle type safety across MCP tools, prompts, and resources?

Type safety is enforced through the central contract in [`src/types/mcp.d.ts`](https://github.com/ai-ql/tuui/blob/main/src/types/mcp.d.ts). This file defines `McpObject` as the canonical shape for server capabilities, `ToolType` for OpenAI-compatible function signatures, and `MCPAPI` as the registry map. The Pinia stores use these types exclusively, ensuring that methods like `callTool` or `getServerFunction` operate on validated structures rather than raw JSON.

### Can TUUI dynamically invoke MCP methods without hardcoding server-specific logic?

Yes. The `getServerFunction` method in [`src/renderer/store/mcp.ts`](https://github.com/ai-ql/tuui/blob/main/src/renderer/store/mcp.ts) performs dynamic lookup using the pattern `servers[serverName][primitiveName][methodName]`. This allows the UI to invoke any MCP method—such as `tools.list`, `prompts.get`, or `resources.read`—without importing server-specific SDKs or writing conditional logic for each provider. The store normalizes all responses through helper utilities like `convertItem` before passing them to UI components.