# MetaMCP Namespace System: Grouping and Configuring MCP Servers

> Discover MetaMCP's namespace system for grouping MCP servers. Configure logical containers for private or public visibility, metadata overrides, and centralized lifecycle management via TRPC API.

- Repository: [metatool-ai/metamcp](https://github.com/metatool-ai/metamcp)
- Tags: internals
- Published: 2026-03-07

---

**MetaMCP namespaces function as logical containers that aggregate one or more MCP servers into a single endpoint, enabling private or public visibility controls, per-tool metadata overrides, and centralized lifecycle management through a type-safe TRPC API.**

The namespace system in the `metatool-ai/metamcp` repository provides the organizational foundation for treating multiple MCP servers as cohesive units. By implementing Zod-validated schemas and database persistence in `@metamcp/zod-types`, this system allows administrators to group servers, customize tool presentations, and enforce access boundaries without modifying upstream server configurations.

## Namespace Data Model and Schema Architecture

At the core of the system are four interconnected entities defined in [`packages/zod-types/src/namespaces.zod.ts`](https://github.com/metatool-ai/metamcp/blob/main/packages/zod-types/src/namespaces.zod.ts):

- **`NamespaceSchema`** – The root container with fields `uuid`, `name`, `description`, and `user_id` (nullable). When `user_id` is `null`, the namespace is public; otherwise, it is private to that user.
- **`NamespaceServer`** – Extends `McpServerSchema` with namespace-specific state including `status` and optional `error_status` fields.
- **`NamespaceTool`** – Extends `ToolSchema` with `serverName`, `serverUuid`, `status`, and override fields (`overrideName`, `overrideTitle`, `overrideDescription`, `overrideAnnotations`).
- **`DatabaseNamespace`** – The raw database representation where timestamp fields are native `Date` objects rather than strings.

All incoming API payloads for creation, updates, status changes, and tool overrides are validated against these schemas before processing.

## Backend Implementation and Business Logic

The concrete enforcement of namespace rules resides in [`apps/backend/src/trpc/namespaces.impl.ts`](https://github.com/metatool-ai/metamcp/blob/main/apps/backend/src/trpc/namespaces.impl.ts). The `create` procedure determines the effective owner through `effectiveUserId` and validates security constraints:

```typescript
const isPublicNamespace = effectiveUserId === null;
// Validation ensures public namespaces cannot contain private MCP servers

```

Key implementation details include:

- **Creation validation** – Prevents public namespaces from referencing private MCP servers to avoid configuration leakage.
- **Access control** – The `findAllAccessibleToUser` method returns both the requesting user’s private namespaces and all public namespaces.
- **Status management** – Separate mutation paths for `updateServerStatus` and `updateToolStatus` allow granular lifecycle control.
- **Metadata overrides** – Permits renaming tools and attaching arbitrary annotations without altering the upstream server definition.

## TRPC API Surface and Available Procedures

The frontend-facing router in [`packages/trpc/src/routers/frontend/namespaces.ts`](https://github.com/metatool-ai/metamcp/blob/main/packages/trpc/src/routers/frontend/namespaces.ts) exposes ten protected procedures:

- **`list`** – Queries accessible namespaces using `ListNamespacesResponseSchema`.
- **`get`** – Retrieves a specific namespace by UUID via `GetNamespaceResponseSchema`.
- **`getTools`** – Fetches tools within a namespace using `GetNamespaceToolsRequestSchema`.
- **`create`** – Creates a new namespace with `CreateNamespaceRequestSchema`.
- **`update`** – Modifies namespace properties via `UpdateNamespaceRequestSchema`.
- **`updateServerStatus`** – Toggles server states using `UpdateNamespaceServerStatusRequestSchema`.
- **`updateToolStatus`** – Controls individual tool availability.
- **`updateToolOverrides`** – Applies custom metadata with `UpdateNamespaceToolOverridesRequestSchema`.
- **`refreshTools`** – Synchronizes tool lists from underlying servers using `RefreshNamespaceToolsRequestSchema`.
- **`delete`** – Removes a namespace and its associations.

## Public vs Private Namespace Configuration

Namespaces support two visibility modes controlled by the `user_id` field:

- **Private namespaces** contain a valid user UUID in `user_id`, restricting list, edit, and retrieval operations to that owner and system administrators.
- **Public namespaces** set `user_id` to `null`, making them readable and usable by anyone, though modification remains restricted to owners and admins.

During creation, the backend enforces a strict relationship rule: public namespaces cannot contain private MCP servers. This validation occurs in [`namespaces.impl.ts`](https://github.com/metatool-ai/metamcp/blob/main/namespaces.impl.ts) (lines 77-82) to ensure that private server configurations never leak through public endpoints.

## Tool Overrides and Annotations

Namespaces enable UI-level customization of tool metadata without requiring changes to the source MCP server. The `NamespaceToolSchema` supports four override fields:

```typescript
overrideName?: string | null;
overrideTitle?: string | null;
overrideDescription?: string | null;
overrideAnnotations?: Record<string, unknown> | null;

```

These overrides merge at request time, allowing teams to add contextual hints such as `readOnlyHint: false` or rename cryptic tool identifiers into human-readable labels for specific use cases.

## Practical Configuration Examples

### Creating a Private Namespace

```typescript
const resp = await trpc.namespaces.create.mutate({
  name: "InternalAnalytics",
  description: "Private data processing tools",
  mcpServerUuids: ["srv-uuid-1", "srv-uuid-2"],
  // user_id defaults to calling user, making this private
});

```

### Creating a Public Namespace

```typescript
await trpc.namespaces.create.mutate({
  name: "OpenUtilities",
  description: "Community-shared utilities",
  mcpServerUuids: ["public-srv-uuid"],
  user_id: null,  // Explicitly public
});

```

The backend rejects this request if any server in `mcpServerUuids` is private.

### Listing Accessible Namespaces

```typescript
const { data } = await trpc.namespaces.list.query();
const summary = data?.map(ns => ({
  uuid: ns.uuid,
  name: ns.name,
  isPublic: ns.user_id === null,
}));

```

### Updating Tool Overrides

```typescript
await trpc.namespaces.updateToolOverrides.mutate({
  namespaceUuid: "ns-uuid",
  toolUuid: "tool-uuid",
  serverUuid: "server-uuid",
  overrideName: "Generate Monthly Report",
  overrideAnnotations: { readOnlyHint: false },
});

```

### Refreshing Tools After Server Changes

```typescript
await trpc.namespaces.refreshTools.mutate({
  namespaceUuid: "ns-uuid",
  tools: []  // Empty array triggers full refresh from MetaMCP connection
});

```

## Summary

- **Namespaces** aggregate multiple MCP servers under a single UUID-identified endpoint with database persistence.
- **Visibility** is determined by the `user_id` field; `null` indicates public access while a UUID restricts the namespace to that owner.
- **Security enforcement** prevents public namespaces from containing private MCP servers, implemented in [`apps/backend/src/trpc/namespaces.impl.ts`](https://github.com/metatool-ai/metamcp/blob/main/apps/backend/src/trpc/namespaces.impl.ts).
- **Tool customization** occurs through `overrideName`, `overrideTitle`, `overrideDescription`, and `overrideAnnotations` fields stored in `NamespaceToolSchema`.
- **API coverage** includes ten TRPC procedures for CRUD operations, status management, and metadata overrides.
- **Schema validation** uses Zod definitions in [`packages/zod-types/src/namespaces.zod.ts`](https://github.com/metatool-ai/metamcp/blob/main/packages/zod-types/src/namespaces.zod.ts) to ensure type safety across the stack.

## Frequently Asked Questions

### How do public and private namespaces differ in MetaMCP?

Private namespaces bind to a specific user via the `user_id` field, limiting access to that user and administrators. Public namespaces set `user_id` to `null`, allowing anyone to list and invoke tools while restricting modifications to authorized owners. The backend explicitly validates that public namespaces cannot reference private MCP servers to maintain security boundaries.

### Where can you customize tool metadata without modifying the upstream server?

Use the `updateToolOverrides` mutation targeting [`packages/trpc/src/routers/frontend/namespaces.ts`](https://github.com/metatool-ai/metamcp/blob/main/packages/trpc/src/routers/frontend/namespaces.ts). This accepts `overrideName`, `overrideTitle`, `overrideDescription`, and `overrideAnnotations` parameters defined in `UpdateNamespaceToolOverridesRequestSchema`, storing them within the namespace-specific tool record for runtime merging.

### What prevents private server configurations from leaking through public namespaces?

The `create` procedure in [`apps/backend/src/trpc/namespaces.impl.ts`](https://github.com/metatool-ai/metamcp/blob/main/apps/backend/src/trpc/namespaces.impl.ts) checks `effectiveUserId` to determine if the namespace is public (`null`). If so, it validates that all referenced `mcpServerUuids` correspond to public servers, rejecting the transaction if any private server is detected in the group.

### Which procedure synchronizes tool definitions after adding servers to a namespace?

The `refreshTools` mutation triggers synchronization with underlying MCP servers. When invoked with an empty `tools` array and a valid `namespaceUuid`, it pulls current tool definitions from the MetaMCP connection and updates the namespace-tool mapping table according to `RefreshNamespaceToolsRequestSchema`.