MetaMCP Namespace System: Grouping and Configuring MCP Servers
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:
NamespaceSchema– The root container with fieldsuuid,name,description, anduser_id(nullable). Whenuser_idisnull, the namespace is public; otherwise, it is private to that user.NamespaceServer– ExtendsMcpServerSchemawith namespace-specific state includingstatusand optionalerror_statusfields.NamespaceTool– ExtendsToolSchemawithserverName,serverUuid,status, and override fields (overrideName,overrideTitle,overrideDescription,overrideAnnotations).DatabaseNamespace– The raw database representation where timestamp fields are nativeDateobjects 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. The create procedure determines the effective owner through effectiveUserId and validates security constraints:
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
findAllAccessibleToUsermethod returns both the requesting user’s private namespaces and all public namespaces. - Status management – Separate mutation paths for
updateServerStatusandupdateToolStatusallow 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 exposes ten protected procedures:
list– Queries accessible namespaces usingListNamespacesResponseSchema.get– Retrieves a specific namespace by UUID viaGetNamespaceResponseSchema.getTools– Fetches tools within a namespace usingGetNamespaceToolsRequestSchema.create– Creates a new namespace withCreateNamespaceRequestSchema.update– Modifies namespace properties viaUpdateNamespaceRequestSchema.updateServerStatus– Toggles server states usingUpdateNamespaceServerStatusRequestSchema.updateToolStatus– Controls individual tool availability.updateToolOverrides– Applies custom metadata withUpdateNamespaceToolOverridesRequestSchema.refreshTools– Synchronizes tool lists from underlying servers usingRefreshNamespaceToolsRequestSchema.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_idtonull, 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 (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:
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
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
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
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
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
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_idfield;nullindicates 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. - Tool customization occurs through
overrideName,overrideTitle,overrideDescription, andoverrideAnnotationsfields stored inNamespaceToolSchema. - 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.tsto 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. 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 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.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →