001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.juneau.bean.mcp.v20260728;
018
019import static org.apache.juneau.commons.utils.CollectionUtils.*;
020import static org.apache.juneau.commons.utils.Shorts.*;
021
022import java.util.*;
023
024import org.apache.juneau.commons.bean.*;
025import org.apache.juneau.marshall.*;
026
027/**
028 * Opaque per-result MCP metadata carried under the JSON-RPC {@code result._meta} property.
029 *
030 * <p>
031 * Every successful v2 result carries server identity under the exact {@code io.modelcontextprotocol/}-prefixed
032 * wire name mandated by the {@code 2026-07-28} schema. W3C trace-context keys ({@code traceparent} /
033 * {@code tracestate} / {@code baggage}) are the schema's explicit exception and remain bare; they are populated
034 * only when an enabled tracer echoes the server span context. Unrecognized metadata members round-trip
035 * losslessly, in insertion order, through the {@code "*"} dynamic-property triplet ({@link #extraKeys()},
036 * {@link #get(String)}, {@link #set(String, Object)}).
037 *
038 * <p>
039 * {@link #KEY_SERVER_INFO} is the single source of truth for the result-identity wire key; the {@code
040 * 2026-07-28} adapter and bean/adapter tests consume this constant rather than repeating the literal string.
041 * The W3C trace-context keys are bare and therefore need no analogous constant: {@link RequestMeta} centralizes
042 * {@link RequestMeta#KEY_TRACEPARENT}, {@link RequestMeta#KEY_TRACESTATE}, and {@link RequestMeta#KEY_BAGGAGE}
043 * for the request side of the same carrier.
044 */
045@Marshalled
046public class ResultMeta {
047
048   /** Exact wire key for the server implementation identity carried in successful result metadata. */
049   public static final String KEY_SERVER_INFO = "io.modelcontextprotocol/serverInfo";
050
051   private Implementation serverInfo;
052   private String traceparent;
053   private String tracestate;
054   private String baggage;
055   private Map<String,Object> extra;
056
057   /**
058    * Server implementation identity.
059    *
060    * @return The server info, or {@code null} if not set.
061    */
062   @BeanProp(KEY_SERVER_INFO)
063   public Implementation getServerInfo() {
064      return serverInfo;
065   }
066
067   /**
068    * Sets the server implementation identity.
069    *
070    * @param value The new value.  Can be <jk>null</jk> to unset the property.
071    * @return This object (for method chaining).
072    */
073   @BeanProp(KEY_SERVER_INFO)
074   public ResultMeta setServerInfo(Implementation value) {
075      serverInfo = value;
076      return this;
077   }
078
079   /**
080    * W3C trace-context parent (bare key; not renamed under the {@code io.modelcontextprotocol/} prefix).
081    *
082    * @return The traceparent value, or {@code null} if not set.
083    */
084   public String getTraceparent() {
085      return traceparent;
086   }
087
088   /**
089    * Sets the W3C trace-context parent.
090    *
091    * @param value The new value.  Can be <jk>null</jk> to unset the property.
092    * @return This object (for method chaining).
093    */
094   public ResultMeta setTraceparent(String value) {
095      traceparent = value;
096      return this;
097   }
098
099   /**
100    * W3C trace-context state (bare key; not renamed under the {@code io.modelcontextprotocol/} prefix).
101    *
102    * @return The tracestate value, or {@code null} if not set.
103    */
104   public String getTracestate() {
105      return tracestate;
106   }
107
108   /**
109    * Sets the W3C trace-context state.
110    *
111    * @param value The new value.  Can be <jk>null</jk> to unset the property.
112    * @return This object (for method chaining).
113    */
114   public ResultMeta setTracestate(String value) {
115      tracestate = value;
116      return this;
117   }
118
119   /**
120    * W3C baggage (bare key; not renamed under the {@code io.modelcontextprotocol/} prefix).
121    *
122    * @return The baggage value, or {@code null} if not set.
123    */
124   public String getBaggage() {
125      return baggage;
126   }
127
128   /**
129    * Sets the W3C baggage.
130    *
131    * @param value The new value.  Can be <jk>null</jk> to unset the property.
132    * @return This object (for method chaining).
133    */
134   public ResultMeta setBaggage(String value) {
135      baggage = value;
136      return this;
137   }
138
139   /**
140    * Extension metadata member keyset.
141    *
142    * <p>
143    * Covers any metadata member other than the identity/trace properties declared above. Preserves insertion
144    * order.
145    *
146    * @return All extension keys on this metadata object.  Never <jk>null</jk>.
147    */
148   @BeanProp("*")
149   public Set<String> extraKeys() {
150      return extra == null ? Collections.emptySet() : u(extra.keySet());
151   }
152
153   /**
154    * Extension metadata member getter.
155    *
156    * @param property The property name.  Must not be <jk>null</jk>.
157    * @return The property value, or <jk>null</jk> if the property does not exist or is not set.
158    */
159   @BeanProp("*")
160   public Object get(String property) {
161      return extra == null ? null : extra.get(property);
162   }
163
164   /**
165    * Extension metadata member setter.
166    *
167    * <p>
168    * The extension map is lazily initialized on first use and preserves insertion order across repeated calls.
169    *
170    * @param property The property name.  Must not be <jk>null</jk>.
171    * @param value The new value for the property.  Can be <jk>null</jk> (stored as <jk>null</jk>).
172    * @return This object (for method chaining).
173    */
174   @BeanProp("*")
175   public ResultMeta set(String property, Object value) {
176      if (extra == null)
177         extra = map();
178      extra.put(property, value);
179      return this;
180   }
181}