Zum Inhalt springen

ID Schema

Dieser Inhalt ist noch nicht in deiner Sprache verfügbar.

A FlowMCP catalog exposes three MCP primitives — Tools, Resources, and Skills (prompts) — across potentially hundreds of schemas from dozens of providers, and references to those primitives turn up everywhere: group definitions, skill placeholders, registry entries, CLI commands, and cross-schema dependencies. Without a unified scheme, a bare name like lookupItem is ambiguous — is it a tool, a resource, or a prompt, and which provider owns it? The ID schema removes that ambiguity by giving every tool, resource, prompt, and shared list exactly one canonical, human-readable, resolvable identifier built from a namespace, a type discriminator, and a name.

Namespace

/

Resource Type

/

Name

acme/tool/lookupItem

The diagram shows the three components of a full ID separated by / delimiters, forming a single unambiguous reference string.


The canonical ID format is a three-segment string separated by /:

namespace/resourceType/name
TypeFormatSlashesExample
Schema-Filenamespace/schema-name1directory-io/records
Toolnamespace/tool/name2directory-io/tool/getEntry
Resourcenamespace/resource/name2directory-io/resource/entryDb
Promptnamespace/prompt/name2directory-io/prompt/intro
Skillnamespace/skill/name2directory-io/skill/audit
Selectionnamespace/selection/name2record-research/selection/lookup
Agentnamespace/agent/name2research/agent/researcher

Distinguishing rule: 1 Slash = Schema-File-ID (Container). 2 Slashes = Primitive-ID (Content).

IDDescription
weather/tool/getForecastTool from the weather provider
weather/resource/supported-citiesResource from the weather provider
weather/prompt/forecast-summaryPrompt from the weather provider
data-research/prompt/record-deep-diveAgent prompt
shared/list/regionCodesShared list reference

Each segment serves a distinct purpose: the namespace identifies the owner, the resource type discriminates the primitive kind, and the name identifies the specific item within that namespace and type.


ComponentPatternRequiredDescription
namespace^[a-z][a-z0-9-]*$YesProvider or agent identifier. Lowercase letters, digits, and hyphens. Must start with a letter.
resourceTypetool, resource, prompt, list, skill, selection, agentRequiredType discriminator. Always required — Short Form is not supported in v4.
name^[a-zA-Z][a-zA-Z0-9-]*$YesResource name. camelCase for tools and resources, kebab-case for prompts. Must start with a letter.

The namespace identifies the owner of the primitive. It is derived from the provider’s domain name or agent name and MUST be unique within its own schemaFolder — each folder is its own registry (see Namespace Rules). The CLI aggregates multiple folders into one catalog, so the same namespace MAY appear in more than one aggregated folder; cross-folder collisions are disambiguated by the optional source coordinate <source>:<namespace> (see Source Coordinate).

weather ← provider namespace
directory ← provider namespace
catalog ← provider namespace
data-research ← agent namespace
shared ← reserved namespace for shared lists

Namespace rules:

  • Lowercase letters, digits, and hyphens only
  • Must start with a letter
  • No dots, underscores, or uppercase characters
  • shared is a reserved namespace (see Namespace Rules)

The resource type discriminates between the seven kinds of addressable primitives in v4.3.0:

TypeMaps ToDefined In
toolMCP server.toolmain.tools
resourceMCP server.resourcemain.resources
promptMCP server.promptmain.prompts
skillMCP server.prompt (skill variant)providers/{ns}/skills/, selections/{name}/skills/, or agents/{name}/skills/ — never main.skills (forbidden)
listShared listlist.meta.name
selectionSelectionselections/{name}/selection.mjs
agentAgentagents/{name}/agent.mjs

The name identifies the specific primitive within its namespace and type. Naming conventions follow the same rules as schema element names (see 01-schema-format.md):

PrimitiveConventionExample
ToolcamelCasegetForecast, getEntry
ResourcecamelCaserecordLookup, regionConfig
Promptkebab-caseforecast-summary, record-deep-dive
Shared ListcamelCaseregionCodes, countryCodes

A schema is a .mjs file containing 1–8 Primitives. The Schema-File-ID identifies this file as a whole.

Format: namespace/schema-name (1 slash)

Schema-File-ID: directory-io/records
└── namespace: directory-io
└── schema-name: records (equals filename without .mjs)
Contains Primitive-IDs:
directory-io/tool/getEntry
directory-io/tool/getEntryHistory
directory-io/resource/entryCache
  • Kebab-case, only lowercase letters and hyphens
  • Thematic, not technical (e.g., records, events, reports — not schema1, tools-v2)
  • For providers with multiple schemas: topic prefix optional (registry-records, registry-events)
  • Matches exactly the filename without .mjs
schemas/v4.1.0/providers/directory-io/records.mjs
└── namespace └── schema-name.mjs
→ Schema-File-ID: directory-io/records

The path segment labelled “namespace” above MUST equal main.namespace of every schema in the directory — it is a binding equality, not merely a label or a derivation. This is the folder↔namespace invariant VAL019 (see 09-validation-rules.md). The grading-monitoring track and the namespace-resolution fallback below consume this invariant.

The namespace of a provider folder is resolved as follows:

  1. Normal case. The namespace is main.namespace, declared in the schema. The folder name MUST equal it (VAL019).
  2. All-unparseable fallback. When all schemas in a folder are unparseable (no readable main.namespace), the folder name is the fallback namespace identifier. The fallback name MUST itself be a valid namespace (^[a-z][a-z0-9-]*$); a folder name that is not a valid namespace is an error, never silently normalised.
  3. Rename-on-parse. Once a schema parses and exposes main.namespace, that field is authoritative and the folder is renamed to match it. A rename is an identity transition, not a delete.

The “all-unparseable → folder name” behaviour is pipeline behaviour, owned by the grading track (see the Grading-Spec 19-folder-layout.md and 22-workbench-island.md). The Schemas-Spec’s job here is only to (a) name the fallback source (the folder name) and (b) assert the post-parse equality invariant (VAL019).


The MCP protocol does not allow slashes in tool names. The CLI maps Spec-IDs to internal MCP tool names:

External Spec-IDInternal MCP Tool Name
directory-io/tool/getEntrygetEntry_directory-io
registry/tool/getRecordgetRecord_registry

Mapping Rule: routeName_namespace (underscore separator, namespace at end). Implemented in #buildToolName() in the CLI.

This mapping is internal. Users and agents always use full Spec-IDs.

A resource does not map to a single tool — each query it declares is exposed as its own callable MCP tool. The wire name is built from the query name and the namespace, using the same name_namespace rule:

External Spec-ID (resource query)Internal MCP Tool Name
mailarchive/resource/mail, query searchMailsearchMail_mailarchive
auto-injected runSql on namespace tokensrunSql_tokens

Mapping Rule (resource query): ${queryName}_${namespace} — the query name, not the resource name, is the wire name. The auto-injected runSql and describeTables follow the same rule. This is the single convention shared by search, call, and serve (see 13-resources.md).

When the CLI aggregates several schemaFolders[] and two folders expose the same namespace, the bare routeName_namespace tool name would collide at the MCP layer (the MCP protocol requires unique tool names). To let both folders coexist, the source coordinate (see Source Coordinate) is carried through #buildToolName() and appended to the internal MCP tool name on collision, so each tool stays addressable:

External Spec-IDInternal MCP Tool Name
folder-a:weather/tool/getForecastgetForecast_weather (uncontested source kept bare)
folder-b:weather/tool/getForecastgetForecast_weather_folder-b (source appended to break the collision)

Without this propagation, two equally-named folders cannot both be served — the MCP layer aborts on the duplicate tool name (the serve dedup/rename/error path). The CLI applies a deterministic dedup-or-rename so the source disambiguation reaches all the way into the served tool name; a genuine duplicate that cannot be disambiguated is reported, never silently dropped.


Short Form is not supported in FlowMCP v4. flowmcp call getRecord (without namespace/type) is not allowed.

Reason: Ambiguity and hidden data provenance. registry/tool/getRecord is explicit — the namespace immediately shows the data source. For LLMs especially, full Spec-IDs are semantically unambiguous.

All CLI commands use full Spec-IDs.


How IDs are resolved to actual files, schemas, and internal references.

3 segments

2 or less

No

Yes

No

Yes

Receive ID string

Split on /

Segment count?

Full form: namespace / type / name

Error: ID001 — full form required

Look up namespace in registry

Namespace found?

Error: namespace not registered

Find schema with matching type + name

Match found?

Error: name not found in namespace

Return file path + internal reference

The diagram shows the resolution flow from receiving an ID string through parsing, namespace lookup, and name matching to the final file path reference.

  1. Parse — split the ID string on / to extract segments. Three segments required: namespace, type, name. Any other count: validation error ID001 (Short Form is not supported).
  2. Find — look up the namespace in the loaded catalog. The catalog is the aggregation of the per-folder registries from schemaFolders[]; each folder maps its namespaces to schema file locations. When more than one aggregated folder owns the namespace, a qualified reference (<source>:<namespace>/..., see Source Coordinate) selects the exact folder, while an unqualified reference resolves first-wins (first folder in schemaFolders[] order) plus a visible collision warning.
  3. Match — within the namespace, find the schema, tool, resource, or prompt with the matching name and type.
  4. Return — produce the resolved reference: file path to the schema file and the internal key path (e.g., main.tools.getForecast).

The ID schema connects to the {{type:name}} placeholder syntax used in skill content (see 14-skills.md). Skill content uses typed placeholders with a type: prefix to reference tools, resources, skills, and input parameters.

PlaceholderInterpretation
{{tool:getEntry}}Tool reference — resolved to a tool in the same schema’s main.tools
{{resource:verifiedEntries}}Resource reference — resolved to a resource in the same schema’s main.resources
{{skill:quick-summary}}Skill reference — resolved to a skill registered in the current scope (selection.skills, agent.skills, or the active namespace’s providers/{ns}/skills/). main.skills is forbidden in v4.0.0.
{{input:recordId}}Input parameter — value provided by the user at runtime

When a skill’s content field contains {{tool:name}}, {{resource:name}}, or {{skill:name}} placeholders, the runtime:

  1. Parses the placeholder type prefix to determine the primitive kind
  2. Resolves the name to a registered primitive within the same schema
  3. Injects the primitive’s description or metadata into the rendered content

The ID schema provides the canonical identifier format (namespace/type/name) used in registries, group definitions, and cross-schema references. Within skill content, the {{type:name}} syntax references primitives scoped to the same schema.


Namespaces are the top-level organizational unit. They must be unique within a folder — each schemaFolder is its own registry. The CLI aggregates multiple folders into one catalog; across aggregated folders the same namespace is allowed and is disambiguated by the optional source coordinate (see Source Coordinate). Namespaces follow strict governance rules.

A schemaFolder is a self-contained registry: namespace uniqueness is required within a folder, not across all folders the CLI knows about. The folder↔namespace invariant VAL019 (see Directory Mapping) already operates per folder — the folder name MUST equal main.namespace of every schema in that folder.

The CLI aggregates the folders listed in schemaFolders[] into a single catalog at load time. Two different folders MAY each carry a schema with the same namespace; this is not an error. References are resolved as follows:

  • Qualified — a reference prefixed with the source coordinate (<source>:<namespace>/..., see Source Coordinate) selects exactly one folder’s namespace.
  • Unqualified — a reference without a source coordinate resolves first-wins across the aggregated folders (the first folder in schemaFolders[] order that owns the namespace), and the CLI emits a visible collision warning so the ambiguity is never silent.

When the CLI aggregates several schemaFolders[], two folders may expose the same namespace. The source coordinate is an optional prefix that qualifies a reference to exactly one folder:

<source>:<namespace>[/<type>/<name>]
folder-a:weather/tool/getForecast
folder-b:weather/tool/getForecast
  • <source> identifies the originating schemaFolder (the source key the CLI assigns to that folder).
  • The separator is a colon (:), chosen so it does not disturb the slash grammar of the ID: the namespace/type/name segments are still split on / exactly as before, and the three-segment count is unchanged. The colon prefix is parsed off before the slash resolution runs.
  • The coordinate applies to all referenceable primitives — tool, resource, prompt, skill, list, selection, and agent.
  • Unqualified references (no <source>: prefix) resolve first-wins across the aggregated folders plus a visible collision warning; the source coordinate is the way to pin the exact folder.
SourceNamespace DerivationExample
API ProviderDomain-derived nameweather, directory, catalog
AgentAgent namedata-research, status-monitor
Shared resourcesReserved sharedshared/list/regionCodes

Providers use their domain-derived name as the namespace. The derivation follows these rules:

  • Remove the TLD (.com, .io, .org, etc.)
  • Lowercase the remainder
  • Replace dots with hyphens
  • Remove www. prefix if present
api.weather.com → weather
directory.io → directory
catalog.com → catalog
pro-api.marketplace.com → marketplace

Agents use their agent name as the namespace. Agent namespaces follow the same pattern constraints as provider namespaces (^[a-z][a-z0-9-]*$).

data-research ← agent that performs record research
status-monitor ← agent that monitors service status
NamespacePurpose
sharedShared lists referenced across schemas. Only list type is valid under this namespace.

The shared namespace is reserved by the FlowMCP specification. Schema authors MUST NOT use shared as a provider or agent namespace.


CodeSeverityRule
ID001errorID MUST contain at least one / separator
ID002errorNamespace MUST match ^[a-z][a-z0-9-]*$
ID003errorResourceType MUST be one of: tool, resource, prompt, list, skill, selection, agent
ID004errorName MUST NOT be empty
ID005errorShort Form is not supported — full form (namespace/type/name) is always required
ID006errorFull form is required everywhere — no context-based inference
flowmcp schema-check --id "weather/tool/getForecast"
0 errors, 0 warnings
ID is valid
flowmcp schema-check --id "WEATHER/tool/getForecast"
ID002 error Namespace "WEATHER" must match ^[a-z][a-z0-9-]*$
1 error, 0 warnings
ID is invalid
flowmcp schema-check --id "getForecast"
ID001 error ID MUST contain at least one "/" separator
1 error, 0 warnings
ID is invalid

weather/tool/getForecast
  • Namespace: weather — the weather provider
  • Type: tool — an MCP tool (API endpoint)
  • Name: getForecast — the specific tool name (camelCase)
weather/resource/supported-cities
  • Namespace: weather — the weather provider
  • Type: resource — an MCP resource (SQLite data)
  • Name: supported-cities — the specific resource
data-research/prompt/record-deep-dive
  • Namespace: data-research — an agent namespace
  • Type: prompt — an MCP prompt (skill)
  • Name: record-deep-dive — the specific prompt (kebab-case)
shared/list/regionCodes
  • Namespace: shared — reserved namespace
  • Type: list — a shared list
  • Name: regionCodes — the specific list (camelCase)

The ID schema unifies several existing identification mechanisms:

Existing MechanismID Schema EquivalentMigration
namespace/file::tool (group format)namespace/tool/nameReplace file::tool with tool/name
::resource::namespace/file::query (group format)namespace/resource/nameReplace prefix + file::query with resource/name
Skill requires.tools entriesnamespace/tool/nameAdd namespace prefix
Shared list ref fieldshared/list/nameWrap in shared/list/ prefix

The ID schema provides a single, consistent format that replaces these context-specific referencing styles. Backward compatibility with existing formats is maintained during migration — see 08-migration.md.