Skip to content

Tweak format of _meta fields for vendor extensions ("publisher", prefix format) #356

Description

@tadasant

This is a follow up to the work done in #331

I have two things in mind here:

  1. "Publisher" data in official metaregistry #29 (comment) brought up the fact that publisher as a key inside _meta is ambiguous with the publisher key we are planning to add to the top level server.json.
  2. I'm realizing the way that these extensions are formatted inside _meta is technically noncompliant with the MCP spec as written:

Key name format: valid _meta key names have two segments: an optional prefix, and a name.

So if we keep it as-written, we'll eventually either need to refactor the core MCP spec to allow for this "prefix-only" key. For example, "io.modelcontextprotocol.registry" is not a valid key in the MCP spec as written (it contains only the "optional" prefix and no "name").

Example of the current state of things:

{
  "name": "my-server",
  "description": "...",
  "_meta": {
    "publisher": { "build_info": "..." },
    "io.modelcontextprotocol.registry": { "id": "...", "published_at": "..." }
  }
}

I think we should tweak both publisher and the way the vendor extensions are formatted to align with the MCP spec. Suggestion:

{
  "name": "my-server",
  "description": "...",
  "_meta": {
    "io.modelcontextprotocol.registry/publisher-metadata": { "build_info": "..." },
    "io.modelcontextprotocol.registry/id": "...",
    "io.modelcontextprotocol.registry/published_at": "..."
  }
}

Or maybe:

{
  "name": "my-server",
  "description": "...",
  "_meta": {
    "io.modelcontextprotocol.registry/unverified": { "build_info": "..." },
    "io.modelcontextprotocol.registry/verified": { "id": "...", "published_at": "..." }
  }
}

Or some combination of the two. I know we just thrashed on this breaking change (cc @toby), but I think making another breaking change now to address both of these problems is easier than later trying to make a SEP-powered change to the _meta field's specifics in the core spec.

What do you think @domdomegg @rdimitrov ?

Activity

  1. rdimitrov commented on Sep 4, 2025

    @rdimitrov
    Member

    So if we keep it as-written, we'll eventually either need to refactor the core MCP spec to allow for this "prefix-only" key. For example, "io.modelcontextprotocol.registry" is not a valid key in the MCP spec as written (it contains only the "optional" prefix and no "name").

    Are we positive on this? In the spec I also see this under "Name" which I read as the name can be empty so having a prefix-only entry under _meta should be spec compliant?

    Unless empty, MUST begin and end with an alphanumeric character ([a-z0-9A-Z]).

    In any case, I think it's correct to follow the already adopted pattern of prefix/name mentioned in the spec so it's probably better to go with it.

    I think I prefer your 2nd suggestion more (properties are not flattened), i.e. -

    {
      "name": "my-server",
      "description": "...",
      "_meta": {
        "io.modelcontextprotocol.registry/official": {
            /* Have all official registry extensions grouped */
            "id": "b6c3a9d5-aa7c-4520-bf5c-b484731bb5b0",
            "published_at": "2025-09-04T14:37:54.899304Z",
            "updated_at": "2025-09-04T14:37:54.899304Z",
            "is_latest": true,
            "release_date": "2025-09-04",
            "publisher": {
              /* Have all publisher information discussed in #29 here */
              "id": "com.microsoft"
            }
         },
        "io.modelcontextprotocol.registry/custom": {
            /* Have the existing custom metadata, currently advertised via publisher here */
            "acme": {
              "is_organisation": true,
              ...
              "license": "MIT License"
             }
          }
       }
    }
  2. tadasant commented on Sep 5, 2025

    @tadasant
    MemberAuthor

    So if we keep it as-written, we'll eventually either need to refactor the core MCP spec to allow for this "prefix-only" key. For example, "io.modelcontextprotocol.registry" is not a valid key in the MCP spec as written (it contains only the "optional" prefix and no "name").

    Are we positive on this? In the spec I also see this under "Name" which I read as the name can be empty so having a prefix-only entry under _meta should be spec compliant?

    That's a fair callout... reading it again, it's somewhat ambiguous:

    Key name format: valid _meta key names have two segments: an optional prefix, and a name.

    Prefix: / If specified, MUST be a series of labels separated by dots (.), followed by a slash (/).

    Name: / Unless empty, MUST begin and end with an alphanumeric character ([a-z0-9A-Z]).

    Read literally, these are valid:

    • "" (no prefix, empty name)
    • "io.modelcontextprotocol.registry/" (prefix with slash, empty name)
    • "io.modelcontextprotocol.registry/name" (normal prefix and name)
    • name (no prefix, just name)

    Technically, io.modelcontextprotocol.registry is valid, but would be seen as a "name", not a "prefix", which isn't ideal as we're trying to align io.modelcontextprotocol.registry with the spec's definition of Prefix.

    I do think the spec would do well to either drop the / requirement for prefixes (maybe? I guess that introduces permanent ambiguity as to whether a string is a 'name' or a 'prefix' when lacking a slash) or disallow empty names... but absent pursuing a SEP discussion at this stage I do still think it'd be better to align with the current state of the spec.

    I think I prefer your 2nd suggestion more (properties are not flattened), i.e. -

    Agree, I'd lean that way too. Don't feel strongly on official/custom vs. verified/unverified. I think the latter is a little more self-descriptive but happy to go the other way if other folks prefer it.

  3. domdomegg commented on Sep 5, 2025

    @domdomegg
    Member

    Happy to make this change, and understand the reasoning.

    I think I prefer:

    • io.modelcontextprotocol.registry/publisher-metadata
      • I think I prefer this quite a bit over unverified or custom. To me 'unverified' suggests it might be from the official registry, but that it hasn't gone through some cryptographic procedure. And 'custom' sounds like it might be custom for subregistries implementing the registry spec.
    • io.modelcontextprotocol.registry/official or io.modelcontextprotocol.registry/verified
      • very slight preference to official, because to me verified feels potentially dangerous if people copy it and tweak it and republish it in subregistries. they shouldn't, but just feels less error prone to avoid having people misinterpret that it's always verified in some way. but again, very slight preference.

    I'd prefer keep these as objects, rather than flattening to e.g. io.modelcontextprotocol.registry/id, io.modelcontextprotocol.registry/published_at, but would also be fine with this.


    I think in the interests of getting to a decision, keen to hear what people's preferences are on the above, and go with something that at least two of us agree on and are happy with :)

  4. rdimitrov commented on Sep 5, 2025

    @rdimitrov
    Member

    Perfect, we are getting there 😃

    I think we want to make 3 decisions here and I think we nailed the first one (correct me I'm wrong)

    Agreed upon:

    • We all agree that the official registry metadata (currently under io.modelcontextprotocol.registry) should be moved to live under io.modelcontextprotocol.registry/official

    What's left:

    1. Where should the current publisher metadata live (currently under _meta.publisher)? Note this is different from what "Publisher" data in official metaregistry #29 is about
    2. Where should the publisher metadata from "Publisher" data in official metaregistry #29 live?

    If I understand it correctly those 2 are different:

    1. This is metadata added by the publisher that may be of interest for another sub-registry, client, etc.
    2. This is metadata added by the registry server about the publisher, i.e. "id": "com.microsoft"(generated, inferred, etc)

    My suggestion for these 2 are: (sorry for reiterating, but I missed to share my reasoning behind them)

    1. Have it under io.modelcontextprotocol.registry/custom, but also happy to have a different name that states "this can be anything".
    2. Have it as part of the official registry extensions (a property of io.modelcontextprotocol.registry/official). My reasoning is since this is provided by the registry and not by the publisher it makes sense to be there next to is_latest and so forth.
  5. tadasant commented on Sep 5, 2025

    @tadasant
    MemberAuthor

    io.modelcontextprotocol.registry/publisher-metadata

    I'm good with this scheme

    io.modelcontextprotocol.registry/official or io.modelcontextprotocol.registry/verified

    Fair reasoning, I'm good with official

    Have it under io.modelcontextprotocol.registry/custom, but also happy to have a different name that states "this can be anything".

    I think we are agreed on this, except Adam and I are saying to call this publisher-metadata instead of custom?

    Have it as part of the official registry extensions (a property of io.modelcontextprotocol.registry/official). My reasoning is since this is provided by the registry and not by the publisher it makes sense to be there next to is_latest and so forth.

    I think we are not yet pitching a solution to #29. If we were, I think we don't need it as a custom extension and would rather be baking it into the core server.json. But I think we can defer that discussion and/or have it on #29.

  6. rdimitrov commented on Sep 5, 2025

    @rdimitrov
    Member
    1. Confirming that io.modelcontextprotocol.registry/official is decided, nice! 👍
    2. Happy to go with io.modelcontextprotocol.registry/publisher-metadata (or even just io.modelcontextprotocol.registry/publisher to make it shorter.

    My reasoning for something that doesn't have "publisher" was the comment you made before -

    I'm realizing this is confusing because we have introduced a separately and basically unrelated field also named publisher inside _meta. Should we rename that one? cc @domdomegg. Maybe that one should be publish or something like unverified?

    If it's still valid maybe other options are "extensions", "vendor-metadata"?

    1. I assumed we wanted to have it too before the go-live, makes sense to leave it out of scope for now if that's the case 👍
  7. tadasant commented on Sep 5, 2025

    @tadasant
    MemberAuthor

    If it's still valid maybe other options are "extensions", "vendor-metadata"?

    Well, I think publisher-metadata mostly resolves the prior naming collision I initially raised. publisher-metadata implies "Publisher's Metadata", which is sufficiently distinct from publisher (implying "Information about the Publisher"). I wouldn't want io.modelcontextprotocol.registry/publisher for that original reason.

    I agree it's not perfect, in that it could easily be read as "Metadata about Publisher" instead of "Publisher's Metadata", and you could probably make the argument that metadata is redundant with the _meta parent), but I understand @domdomegg 's objections to unverified and custom. And I think extensions & vendor-metadata don't communicate its provenance (i.e. self-reported) properly vs. /official.

    A few I think I'd like above publisher-metadata if anyone wants to +1:

    • io.modelcontextprotocol.registry/publisher-provided
    • io.modelcontextprotocol.registry/self-declared
    • io.modelcontextprotocol.registry/publisher-declared
  8. domdomegg commented on Sep 5, 2025

    @domdomegg
    Member

    I like all three of those! Probably my favorite is io.modelcontextprotocol.registry/publisher-provided

  9. rdimitrov commented on Sep 5, 2025

    @rdimitrov
    Member

    I'm in favour of "publisher-provided" too! 👍

    @domdomegg - is there anything else that's missing to make the change?

  10. domdomegg commented on Sep 5, 2025

    @domdomegg
    Member

    Nope don't think anything else is missing, good to implement!

    So it's:

    {
      "name": "my-server",
      "description": "...",
      "_meta": {
        "io.modelcontextprotocol.registry/official": {
            /* Have all official registry extensions grouped */
            "id": "b6c3a9d5-aa7c-4520-bf5c-b484731bb5b0",
            "published_at": "2025-09-04T14:37:54.899304Z",
            "updated_at": "2025-09-04T14:37:54.899304Z",
            "is_latest": true
         },
        "io.modelcontextprotocol.registry/publisher-provided": {
            /* Have the existing custom metadata, currently advertised via publisher here */
            "is_organisation": true,
            ...
            "license": "MIT License"
          }
       }
    }
    
  11. self-assigned this
    on Sep 7, 2025
  12. added a commit that references this issue on Sep 7, 2025
    4ac6528
  13. added a commit that references this issue on Sep 8, 2025
    ef46077
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

go-live blockerThis issue is one we need to address prior to initial go-liveimplementation workShovel-ready to write code

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions