001/*
002 * SPDX-License-Identifier: Apache-2.0
003 *
004 * Copyright 2025-2026 The Enola <https://enola.dev> Authors
005 *
006 * Licensed under the Apache License, Version 2.0 (the "License");
007 * you may not use this file except in compliance with the License.
008 * You may obtain a copy of the License at
009 *
010 *     https://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package dev.enola.ai.mcp;
019
020import dev.enola.common.io.object.WithSchema;
021
022import io.modelcontextprotocol.spec.McpSchema;
023
024import org.jspecify.annotations.Nullable;
025
026import java.net.URI;
027import java.time.Duration;
028import java.util.ArrayList;
029import java.util.HashMap;
030import java.util.List;
031import java.util.Map;
032
033/**
034 * Configuration how to connect to an MCP Server.
035 *
036 * <p>This is inspired by e.g. Claude's or VSC's mcp.json etc.
037 *
038 * @see McpServerMetadata
039 */
040public class McpServerConnectionsConfig extends WithSchema {
041    // implements Identifiable ?  String id() { return origin.toString(); }
042
043    /** Origin of configuration; e.g. file:/.../mcp.yaml, or something like that. */
044    // TODO extends WithOrigin implements HasOrigin; and set it in ObjectReader
045    public URI origin;
046
047    public Map<String, ServerConnection> servers = new HashMap<>();
048
049    // public final Map<String, Input> inputs = new HashMap<>();
050
051    public static class ServerConnection {
052
053        public ServerConnection() {}
054
055        public ServerConnection(ServerConnection other) {
056            this.origin = other.origin;
057            this.docs = other.docs;
058            this.type = other.type;
059            this.command = other.command;
060            this.args = other.args;
061            this.env = other.env;
062            this.url = other.url;
063            this.headers = other.headers;
064            this.timeout = other.timeout;
065            this.roots = other.roots;
066            this.log = other.log;
067        }
068
069        /**
070         * Origin of configuration; e.g. file:/.../mcp.yaml#github, or something like that. This is
071         * automatically set by the {@link McpLoader}. (This originally used to be confused with
072         * {@link #docs}.)
073         */
074        // TODO extends WithOrigin implements HasOrigin; and set it in ObjectReader
075        public @Nullable URI origin;
076
077        /**
078         * Server's homepage or GitHub repo, or whatever uniquely identifies it.
079         *
080         * <p>There could be (external) sameAs equivalencies defined for disambiguation.
081         *
082         * <p>This is NOT its "package", so don't put a NPM or Container Image etc. 'PURL' here.
083         */
084        // TODO Use another name than 'origin' here, to avoid confusion with the outer origin above?
085        public String docs;
086
087        public enum Type {
088            stdio,
089            http,
090            sse
091        }
092
093        public Type type = Type.stdio;
094
095        // STDIO; like io.modelcontextprotocol.client.transport.ServerParameters
096        public String command;
097        public List<String> args = new ArrayList<>();
098        public Map<String, String> env = new HashMap<>();
099
100        // HTTP; like com.google.adk.tools.mcp.SseServerParameters
101        public String url;
102        public Map<String, String> headers = new HashMap<>();
103        public Duration timeout = Duration.ofSeconds(7);
104
105        public boolean roots = false;
106
107        public McpSchema.LoggingLevel log = McpSchema.LoggingLevel.WARNING;
108    }
109
110    /*
111        public static class Input {
112            public enum Type {
113                http
114            }
115
116            public Type type;
117            public String id;
118            public String description;
119            public boolean password;
120        }
121    */
122    // TODO public Optional<String> validate() {}
123}