diff --git a/src/main/java/io/naftiko/Capability.java b/src/main/java/io/naftiko/Capability.java index dfc54a4..d2f79bc 100644 --- a/src/main/java/io/naftiko/Capability.java +++ b/src/main/java/io/naftiko/Capability.java @@ -24,18 +24,18 @@ import io.naftiko.engine.ExternalRefResolver; import io.naftiko.spec.ExecutionContext; import io.naftiko.engine.consumes.ClientAdapter; -import io.naftiko.engine.consumes.HttpClientAdapter; -import io.naftiko.engine.exposes.ApiServerAdapter; -import io.naftiko.engine.exposes.McpServerAdapter; +import io.naftiko.engine.consumes.http.HttpClientAdapter; import io.naftiko.engine.exposes.ServerAdapter; -import io.naftiko.engine.exposes.SkillServerAdapter; +import io.naftiko.engine.exposes.mcp.McpServerAdapter; +import io.naftiko.engine.exposes.rest.RestServerAdapter; +import io.naftiko.engine.exposes.skill.SkillServerAdapter; import io.naftiko.spec.NaftikoSpec; import io.naftiko.spec.consumes.ClientSpec; -import io.naftiko.spec.consumes.HttpClientSpec; -import io.naftiko.spec.exposes.ApiServerSpec; -import io.naftiko.spec.exposes.McpServerSpec; +import io.naftiko.spec.consumes.http.HttpClientSpec; import io.naftiko.spec.exposes.ServerSpec; -import io.naftiko.spec.exposes.SkillServerSpec; +import io.naftiko.spec.exposes.mcp.McpServerSpec; +import io.naftiko.spec.exposes.rest.RestServerSpec; +import io.naftiko.spec.exposes.skill.SkillServerSpec; /** * Main Capability class that initializes and manages adapters based on configuration @@ -86,8 +86,8 @@ public String getVariable(String key) { } for (ServerSpec serverSpec : spec.getCapability().getExposes()) { - if ("api".equals(serverSpec.getType())) { - this.serverAdapters.add(new ApiServerAdapter(this, (ApiServerSpec) serverSpec)); + if ("rest".equals(serverSpec.getType())) { + this.serverAdapters.add(new RestServerAdapter(this, (RestServerSpec) serverSpec)); } else if ("mcp".equals(serverSpec.getType())) { this.serverAdapters.add(new McpServerAdapter(this, (McpServerSpec) serverSpec)); } else if ("skill".equals(serverSpec.getType())) { diff --git a/src/main/java/io/naftiko/engine/consumes/ClientAdapter.java b/src/main/java/io/naftiko/engine/consumes/ClientAdapter.java index dcc0fb8..88aee1f 100644 --- a/src/main/java/io/naftiko/engine/consumes/ClientAdapter.java +++ b/src/main/java/io/naftiko/engine/consumes/ClientAdapter.java @@ -16,7 +16,7 @@ import io.naftiko.Capability; import io.naftiko.engine.Adapter; import io.naftiko.spec.consumes.ClientSpec; -import io.naftiko.spec.consumes.HttpClientSpec; +import io.naftiko.spec.consumes.http.HttpClientSpec; /** * Client Adapter implementation diff --git a/src/main/java/io/naftiko/engine/consumes/HttpClientAdapter.java b/src/main/java/io/naftiko/engine/consumes/http/HttpClientAdapter.java similarity index 82% rename from src/main/java/io/naftiko/engine/consumes/HttpClientAdapter.java rename to src/main/java/io/naftiko/engine/consumes/http/HttpClientAdapter.java index 61f5a69..c2a9fdd 100644 --- a/src/main/java/io/naftiko/engine/consumes/HttpClientAdapter.java +++ b/src/main/java/io/naftiko/engine/consumes/http/HttpClientAdapter.java @@ -11,7 +11,7 @@ * or implied. See the License for the specific language governing permissions and limitations under * the License. */ -package io.naftiko.engine.consumes; +package io.naftiko.engine.consumes.http; import org.restlet.Client; import org.restlet.Request; @@ -19,15 +19,16 @@ import org.restlet.data.ChallengeScheme; import io.naftiko.Capability; import io.naftiko.engine.Resolver; +import io.naftiko.engine.consumes.ClientAdapter; import io.naftiko.spec.InputParameterSpec; -import io.naftiko.spec.consumes.ApiKeyAuthenticationSpec; -import io.naftiko.spec.consumes.AuthenticationSpec; -import io.naftiko.spec.consumes.BasicAuthenticationSpec; -import io.naftiko.spec.consumes.BearerAuthenticationSpec; -import io.naftiko.spec.consumes.DigestAuthenticationSpec; -import io.naftiko.spec.consumes.HttpClientOperationSpec; -import io.naftiko.spec.consumes.HttpClientResourceSpec; -import io.naftiko.spec.consumes.HttpClientSpec; +import io.naftiko.spec.consumes.http.HttpApiKeyAuthenticationSpec; +import io.naftiko.spec.consumes.http.HttpAuthenticationSpec; +import io.naftiko.spec.consumes.http.HttpBasicAuthenticationSpec; +import io.naftiko.spec.consumes.http.HttpBearerAuthenticationSpec; +import io.naftiko.spec.consumes.http.HttpDigestAuthenticationSpec; +import io.naftiko.spec.consumes.http.HttpClientOperationSpec; +import io.naftiko.spec.consumes.http.HttpClientResourceSpec; +import io.naftiko.spec.consumes.http.HttpClientSpec; import static org.restlet.data.Protocol.HTTP; import static org.restlet.data.Protocol.HTTPS; import java.util.Map; @@ -84,7 +85,7 @@ public void setHeaders(Request request) { */ public void setChallengeResponse(Request serverRequest, Request clientRequest, String targetRef, Map parameters) { - AuthenticationSpec authenticationSpec = getHttpClientSpec().getAuthentication(); + HttpAuthenticationSpec authenticationSpec = getHttpClientSpec().getAuthentication(); if (authenticationSpec != null) { // Add authentication headers if needed @@ -93,8 +94,8 @@ public void setChallengeResponse(Request serverRequest, Request clientRequest, S switch (type) { case "basic": - BasicAuthenticationSpec basicAuth = - (BasicAuthenticationSpec) authenticationSpec; + HttpBasicAuthenticationSpec basicAuth = + (HttpBasicAuthenticationSpec) authenticationSpec; challengeResponse = new ChallengeResponse(ChallengeScheme.HTTP_BASIC); challengeResponse.setIdentifier( Resolver.resolveMustacheTemplate(basicAuth.getUsername(), parameters)); @@ -105,8 +106,8 @@ public void setChallengeResponse(Request serverRequest, Request clientRequest, S break; case "digest": - DigestAuthenticationSpec digestAuth = - (DigestAuthenticationSpec) authenticationSpec; + HttpDigestAuthenticationSpec digestAuth = + (HttpDigestAuthenticationSpec) authenticationSpec; challengeResponse = new ChallengeResponse(ChallengeScheme.HTTP_DIGEST); challengeResponse.setIdentifier( Resolver.resolveMustacheTemplate(digestAuth.getUsername(), parameters)); @@ -116,8 +117,8 @@ public void setChallengeResponse(Request serverRequest, Request clientRequest, S break; case "bearer": - BearerAuthenticationSpec bearerAuth = - (BearerAuthenticationSpec) authenticationSpec; + HttpBearerAuthenticationSpec bearerAuth = + (HttpBearerAuthenticationSpec) authenticationSpec; challengeResponse = new ChallengeResponse(ChallengeScheme.HTTP_OAUTH_BEARER); challengeResponse.setRawValue( Resolver.resolveMustacheTemplate(bearerAuth.getToken(), parameters)); @@ -125,8 +126,8 @@ public void setChallengeResponse(Request serverRequest, Request clientRequest, S break; case "apikey": - ApiKeyAuthenticationSpec apiKeyAuth = - (ApiKeyAuthenticationSpec) authenticationSpec; + HttpApiKeyAuthenticationSpec apiKeyAuth = + (HttpApiKeyAuthenticationSpec) authenticationSpec; String key = Resolver.resolveMustacheTemplate(apiKeyAuth.getKey(), parameters); String value = Resolver.resolveMustacheTemplate(apiKeyAuth.getValue(), parameters); diff --git a/src/main/java/io/naftiko/engine/consumes/Operation.java b/src/main/java/io/naftiko/engine/consumes/http/HttpOperation.java similarity index 80% rename from src/main/java/io/naftiko/engine/consumes/Operation.java rename to src/main/java/io/naftiko/engine/consumes/http/HttpOperation.java index 410a20c..9ce5cf9 100644 --- a/src/main/java/io/naftiko/engine/consumes/Operation.java +++ b/src/main/java/io/naftiko/engine/consumes/http/HttpOperation.java @@ -11,7 +11,7 @@ * or implied. See the License for the specific language governing permissions and limitations under * the License. */ -package io.naftiko.engine.consumes; +package io.naftiko.engine.consumes.http; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; @@ -19,17 +19,17 @@ /** * HTTP Operation representation */ -public class Operation { +public class HttpOperation { private volatile String httpMethod; private volatile String targetUri; - private List parameters; + private List parameters; - private final List responses; + private final List responses; - public Operation() { + public HttpOperation() { super(); this.httpMethod = null; this.targetUri = null; @@ -37,7 +37,7 @@ public Operation() { this.responses = new CopyOnWriteArrayList<>(); } - public List getParameters() { + public List getParameters() { return parameters; } @@ -49,7 +49,7 @@ public String getTargetUri() { return targetUri; } - public List getResponses() { + public List getResponses() { return this.responses; } diff --git a/src/main/java/io/naftiko/engine/consumes/Parameter.java b/src/main/java/io/naftiko/engine/consumes/http/HttpParameter.java similarity index 90% rename from src/main/java/io/naftiko/engine/consumes/Parameter.java rename to src/main/java/io/naftiko/engine/consumes/http/HttpParameter.java index 8c5d974..6a81326 100644 --- a/src/main/java/io/naftiko/engine/consumes/Parameter.java +++ b/src/main/java/io/naftiko/engine/consumes/http/HttpParameter.java @@ -11,11 +11,11 @@ * or implied. See the License for the specific language governing permissions and limitations under * the License. */ -package io.naftiko.engine.consumes; +package io.naftiko.engine.consumes.http; /** * HTTP Parameter representation */ -public class Parameter { +public class HttpParameter { } diff --git a/src/main/java/io/naftiko/engine/consumes/Response.java b/src/main/java/io/naftiko/engine/consumes/http/HttpResponse.java similarity index 79% rename from src/main/java/io/naftiko/engine/consumes/Response.java rename to src/main/java/io/naftiko/engine/consumes/http/HttpResponse.java index 3bd0b8e..aee4c59 100644 --- a/src/main/java/io/naftiko/engine/consumes/Response.java +++ b/src/main/java/io/naftiko/engine/consumes/http/HttpResponse.java @@ -11,22 +11,22 @@ * or implied. See the License for the specific language governing permissions and limitations under * the License. */ -package io.naftiko.engine.consumes; +package io.naftiko.engine.consumes.http; import java.util.List; /** * HTTP Response representation */ -public class Response { +public class HttpResponse { - private List parameters; + private List parameters; - public Response() { + public HttpResponse() { super(); } - public List getParameters() { + public List getParameters() { return parameters; } diff --git a/src/main/java/io/naftiko/engine/LookupExecutor.java b/src/main/java/io/naftiko/engine/exposes/LookupExecutor.java similarity index 99% rename from src/main/java/io/naftiko/engine/LookupExecutor.java rename to src/main/java/io/naftiko/engine/exposes/LookupExecutor.java index 06c47f5..8d19907 100644 --- a/src/main/java/io/naftiko/engine/LookupExecutor.java +++ b/src/main/java/io/naftiko/engine/exposes/LookupExecutor.java @@ -11,7 +11,7 @@ * or implied. See the License for the specific language governing permissions and limitations under * the License. */ -package io.naftiko.engine; +package io.naftiko.engine.exposes; import java.util.Iterator; import java.util.List; diff --git a/src/main/java/io/naftiko/engine/exposes/OperationStepExecutor.java b/src/main/java/io/naftiko/engine/exposes/OperationStepExecutor.java index 925be8a..ae4e85e 100644 --- a/src/main/java/io/naftiko/engine/exposes/OperationStepExecutor.java +++ b/src/main/java/io/naftiko/engine/exposes/OperationStepExecutor.java @@ -29,18 +29,17 @@ import com.fasterxml.jackson.databind.node.NullNode; import com.fasterxml.jackson.databind.node.ObjectNode; import io.naftiko.Capability; -import io.naftiko.engine.LookupExecutor; import io.naftiko.engine.Resolver; import io.naftiko.engine.StepExecutionContext; import io.naftiko.engine.consumes.ClientAdapter; -import io.naftiko.engine.consumes.HttpClientAdapter; +import io.naftiko.engine.consumes.http.HttpClientAdapter; import io.naftiko.spec.InputParameterSpec; import io.naftiko.spec.OutputParameterSpec; -import io.naftiko.spec.consumes.HttpClientOperationSpec; +import io.naftiko.spec.consumes.http.HttpClientOperationSpec; import io.naftiko.spec.exposes.ServerCallSpec; -import io.naftiko.spec.exposes.ApiServerOperationSpec; -import io.naftiko.spec.exposes.ApiServerResourceSpec; -import io.naftiko.spec.exposes.ApiServerSpec; +import io.naftiko.spec.exposes.rest.RestServerOperationSpec; +import io.naftiko.spec.exposes.rest.RestServerResourceSpec; +import io.naftiko.spec.exposes.rest.RestServerSpec; import io.naftiko.spec.exposes.OperationStepSpec; import io.naftiko.spec.exposes.OperationStepCallSpec; import io.naftiko.spec.exposes.OperationStepLookupSpec; @@ -53,7 +52,7 @@ * - Finding the appropriate client adapter and operation * - Executing the client request * - * Used by both ApiResourceRestlet and McpToolHandler to avoid duplication. + * Used by both RestResourceRestlet and McpToolHandler to avoid duplication. */ public class OperationStepExecutor { @@ -70,8 +69,8 @@ public OperationStepExecutor(Capability capability) { * server-level, resource-level and operation-level InputParameterSpec entries. */ public Map resolveInputParametersFromRequest(Request request, - ApiServerSpec serverSpec, ApiServerResourceSpec resourceSpec, - ApiServerOperationSpec serverOp) { + RestServerSpec serverSpec, RestServerResourceSpec resourceSpec, + RestServerOperationSpec serverOp) { Map params = new ConcurrentHashMap<>(); JsonNode tmpRoot = null; diff --git a/src/main/java/io/naftiko/engine/exposes/McpPromptHandler.java b/src/main/java/io/naftiko/engine/exposes/mcp/McpPromptHandler.java similarity index 97% rename from src/main/java/io/naftiko/engine/exposes/McpPromptHandler.java rename to src/main/java/io/naftiko/engine/exposes/mcp/McpPromptHandler.java index 06eb166..edc4e69 100644 --- a/src/main/java/io/naftiko/engine/exposes/McpPromptHandler.java +++ b/src/main/java/io/naftiko/engine/exposes/mcp/McpPromptHandler.java @@ -11,7 +11,7 @@ * or implied. See the License for the specific language governing permissions and limitations under * the License. */ -package io.naftiko.engine.exposes; +package io.naftiko.engine.exposes.mcp; import java.io.IOException; import java.net.URI; @@ -25,8 +25,8 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.regex.Matcher; import java.util.regex.Pattern; -import io.naftiko.spec.exposes.McpPromptMessageSpec; -import io.naftiko.spec.exposes.McpServerPromptSpec; +import io.naftiko.spec.exposes.mcp.McpPromptMessageSpec; +import io.naftiko.spec.exposes.mcp.McpServerPromptSpec; /** * Handles MCP {@code prompts/get} requests by rendering prompt templates. diff --git a/src/main/java/io/naftiko/engine/exposes/McpProtocolDispatcher.java b/src/main/java/io/naftiko/engine/exposes/mcp/McpProtocolDispatcher.java similarity index 98% rename from src/main/java/io/naftiko/engine/exposes/McpProtocolDispatcher.java rename to src/main/java/io/naftiko/engine/exposes/mcp/McpProtocolDispatcher.java index dfd176e..069df91 100644 --- a/src/main/java/io/naftiko/engine/exposes/McpProtocolDispatcher.java +++ b/src/main/java/io/naftiko/engine/exposes/mcp/McpProtocolDispatcher.java @@ -11,7 +11,7 @@ * or implied. See the License for the specific language governing permissions and limitations under * the License. */ -package io.naftiko.engine.exposes; +package io.naftiko.engine.exposes.mcp; import java.util.List; import java.util.Map; @@ -23,9 +23,9 @@ import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; import io.modelcontextprotocol.spec.McpSchema; -import io.naftiko.spec.exposes.McpPromptArgumentSpec; -import io.naftiko.spec.exposes.McpServerPromptSpec; -import io.naftiko.spec.exposes.McpServerResourceSpec; +import io.naftiko.spec.exposes.mcp.McpPromptArgumentSpec; +import io.naftiko.spec.exposes.mcp.McpServerPromptSpec; +import io.naftiko.spec.exposes.mcp.McpServerResourceSpec; /** * Transport-agnostic MCP JSON-RPC protocol dispatcher. diff --git a/src/main/java/io/naftiko/engine/exposes/McpResourceHandler.java b/src/main/java/io/naftiko/engine/exposes/mcp/McpResourceHandler.java similarity index 98% rename from src/main/java/io/naftiko/engine/exposes/McpResourceHandler.java rename to src/main/java/io/naftiko/engine/exposes/mcp/McpResourceHandler.java index acfebf0..251a7ad 100644 --- a/src/main/java/io/naftiko/engine/exposes/McpResourceHandler.java +++ b/src/main/java/io/naftiko/engine/exposes/mcp/McpResourceHandler.java @@ -11,7 +11,7 @@ * or implied. See the License for the specific language governing permissions and limitations under * the License. */ -package io.naftiko.engine.exposes; +package io.naftiko.engine.exposes.mcp; import java.io.IOException; import java.net.URI; @@ -28,7 +28,8 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; import io.naftiko.Capability; -import io.naftiko.spec.exposes.McpServerResourceSpec; +import io.naftiko.engine.exposes.OperationStepExecutor; +import io.naftiko.spec.exposes.mcp.McpServerResourceSpec; /** * Handles MCP resource reads by serving either dynamic (HTTP-backed) or static (file-backed) diff --git a/src/main/java/io/naftiko/engine/exposes/McpServerAdapter.java b/src/main/java/io/naftiko/engine/exposes/mcp/McpServerAdapter.java similarity index 95% rename from src/main/java/io/naftiko/engine/exposes/McpServerAdapter.java rename to src/main/java/io/naftiko/engine/exposes/mcp/McpServerAdapter.java index 2141e77..c82dac2 100644 --- a/src/main/java/io/naftiko/engine/exposes/McpServerAdapter.java +++ b/src/main/java/io/naftiko/engine/exposes/mcp/McpServerAdapter.java @@ -11,7 +11,7 @@ * or implied. See the License for the specific language governing permissions and limitations under * the License. */ -package io.naftiko.engine.exposes; +package io.naftiko.engine.exposes.mcp; import java.util.ArrayList; import java.util.HashMap; @@ -24,9 +24,10 @@ import org.restlet.Context; import io.modelcontextprotocol.spec.McpSchema; import io.naftiko.Capability; +import io.naftiko.engine.exposes.ServerAdapter; import io.naftiko.spec.InputParameterSpec; -import io.naftiko.spec.exposes.McpServerSpec; -import io.naftiko.spec.exposes.McpServerToolSpec; +import io.naftiko.spec.exposes.mcp.McpServerSpec; +import io.naftiko.spec.exposes.mcp.McpServerToolSpec; /** * MCP Server Adapter implementation. @@ -46,7 +47,7 @@ public class McpServerAdapter extends ServerAdapter { private Server jettyServer; /** Stdio handler and thread — only initialized for stdio transport */ - private volatile StdioJsonRpcHandler stdioHandler; + private volatile McpStdioHandler stdioHandler; private volatile Thread stdioThread; private final McpToolHandler toolHandler; @@ -102,7 +103,7 @@ private void initHttpTransport(McpServerSpec serverSpec) { jettyServer.addConnector(connector); // Set the MCP handler - jettyServer.setHandler(new JettyMcpStreamableHandler(this)); + jettyServer.setHandler(new McpStreamableHandler(this)); } /** @@ -110,7 +111,7 @@ private void initHttpTransport(McpServerSpec serverSpec) { */ private void initStdioTransport() { McpProtocolDispatcher dispatcher = new McpProtocolDispatcher(this); - this.stdioHandler = new StdioJsonRpcHandler(dispatcher); + this.stdioHandler = new McpStdioHandler(dispatcher); } /** diff --git a/src/main/java/io/naftiko/engine/exposes/StdioJsonRpcHandler.java b/src/main/java/io/naftiko/engine/exposes/mcp/McpStdioHandler.java similarity index 95% rename from src/main/java/io/naftiko/engine/exposes/StdioJsonRpcHandler.java rename to src/main/java/io/naftiko/engine/exposes/mcp/McpStdioHandler.java index 7fe5b4f..061b6c3 100644 --- a/src/main/java/io/naftiko/engine/exposes/StdioJsonRpcHandler.java +++ b/src/main/java/io/naftiko/engine/exposes/mcp/McpStdioHandler.java @@ -11,7 +11,7 @@ * or implied. See the License for the specific language governing permissions and limitations under * the License. */ -package io.naftiko.engine.exposes; +package io.naftiko.engine.exposes.mcp; import java.io.BufferedReader; import java.io.IOException; @@ -36,7 +36,7 @@ *

All diagnostic logging goes to stderr since stdout is reserved for * the JSON-RPC protocol.

*/ -public class StdioJsonRpcHandler implements Runnable { +public class McpStdioHandler implements Runnable { private final McpProtocolDispatcher dispatcher; private final InputStream input; @@ -46,14 +46,14 @@ public class StdioJsonRpcHandler implements Runnable { /** * Create a stdio handler using System.in / System.out. */ - public StdioJsonRpcHandler(McpProtocolDispatcher dispatcher) { + public McpStdioHandler(McpProtocolDispatcher dispatcher) { this(dispatcher, System.in, System.out); } /** * Create a stdio handler with explicit streams (for testing). */ - public StdioJsonRpcHandler(McpProtocolDispatcher dispatcher, + public McpStdioHandler(McpProtocolDispatcher dispatcher, InputStream input, OutputStream output) { this.dispatcher = dispatcher; this.input = input; diff --git a/src/main/java/io/naftiko/engine/exposes/JettyMcpStreamableHandler.java b/src/main/java/io/naftiko/engine/exposes/mcp/McpStreamableHandler.java similarity index 97% rename from src/main/java/io/naftiko/engine/exposes/JettyMcpStreamableHandler.java rename to src/main/java/io/naftiko/engine/exposes/mcp/McpStreamableHandler.java index f737ce7..1ceec85 100644 --- a/src/main/java/io/naftiko/engine/exposes/JettyMcpStreamableHandler.java +++ b/src/main/java/io/naftiko/engine/exposes/mcp/McpStreamableHandler.java @@ -11,7 +11,7 @@ * or implied. See the License for the specific language governing permissions and limitations under * the License. */ -package io.naftiko.engine.exposes; +package io.naftiko.engine.exposes.mcp; import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; @@ -42,7 +42,7 @@ * Delegates protocol dispatch to {@link McpProtocolDispatcher} and adds * HTTP-specific concerns: session management, HTTP status codes, content types. */ -public class JettyMcpStreamableHandler extends Handler.Abstract { +public class McpStreamableHandler extends Handler.Abstract { private static final String HEADER_MCP_SESSION_ID = "Mcp-Session-Id"; @@ -50,7 +50,7 @@ public class JettyMcpStreamableHandler extends Handler.Abstract { private final ObjectMapper mapper; private final Map activeSessions; - public JettyMcpStreamableHandler(McpServerAdapter adapter) { + public McpStreamableHandler(McpServerAdapter adapter) { this.dispatcher = new McpProtocolDispatcher(adapter); this.mapper = dispatcher.getMapper(); this.activeSessions = new ConcurrentHashMap<>(); diff --git a/src/main/java/io/naftiko/engine/exposes/McpToolHandler.java b/src/main/java/io/naftiko/engine/exposes/mcp/McpToolHandler.java similarity index 97% rename from src/main/java/io/naftiko/engine/exposes/McpToolHandler.java rename to src/main/java/io/naftiko/engine/exposes/mcp/McpToolHandler.java index 30dfc22..de15235 100644 --- a/src/main/java/io/naftiko/engine/exposes/McpToolHandler.java +++ b/src/main/java/io/naftiko/engine/exposes/mcp/McpToolHandler.java @@ -11,7 +11,7 @@ * or implied. See the License for the specific language governing permissions and limitations under * the License. */ -package io.naftiko.engine.exposes; +package io.naftiko.engine.exposes.mcp; import java.io.IOException; import java.util.HashMap; @@ -21,7 +21,8 @@ import java.util.logging.Logger; import io.modelcontextprotocol.spec.McpSchema; import io.naftiko.Capability; -import io.naftiko.spec.exposes.McpServerToolSpec; +import io.naftiko.engine.exposes.OperationStepExecutor; +import io.naftiko.spec.exposes.mcp.McpServerToolSpec; /** * Handles MCP tool calls by delegating to consumed HTTP operations. diff --git a/src/main/java/io/naftiko/engine/exposes/ApiResourceRestlet.java b/src/main/java/io/naftiko/engine/exposes/rest/RestResourceRestlet.java similarity index 93% rename from src/main/java/io/naftiko/engine/exposes/ApiResourceRestlet.java rename to src/main/java/io/naftiko/engine/exposes/rest/RestResourceRestlet.java index a84cad5..0205dbc 100644 --- a/src/main/java/io/naftiko/engine/exposes/ApiResourceRestlet.java +++ b/src/main/java/io/naftiko/engine/exposes/rest/RestResourceRestlet.java @@ -11,7 +11,7 @@ * or implied. See the License for the specific language governing permissions and limitations under * the License. */ -package io.naftiko.engine.exposes; +package io.naftiko.engine.exposes.rest; import org.restlet.Context; import org.restlet.Request; @@ -23,12 +23,13 @@ import io.naftiko.engine.Converter; import io.naftiko.engine.Resolver; import io.naftiko.engine.consumes.ClientAdapter; -import io.naftiko.engine.consumes.HttpClientAdapter; +import io.naftiko.engine.consumes.http.HttpClientAdapter; +import io.naftiko.engine.exposes.OperationStepExecutor; import io.naftiko.spec.OutputParameterSpec; -import io.naftiko.spec.exposes.ApiServerForwardSpec; -import io.naftiko.spec.exposes.ApiServerOperationSpec; -import io.naftiko.spec.exposes.ApiServerResourceSpec; -import io.naftiko.spec.exposes.ApiServerSpec; +import io.naftiko.spec.exposes.rest.RestServerForwardSpec; +import io.naftiko.spec.exposes.rest.RestServerOperationSpec; +import io.naftiko.spec.exposes.rest.RestServerResourceSpec; +import io.naftiko.spec.exposes.rest.RestServerSpec; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.NullNode; @@ -37,17 +38,17 @@ import java.util.concurrent.ConcurrentHashMap; /** - * Restlet that handles calls to an API resource + * Restlet that handles calls to a REST resource */ -public class ApiResourceRestlet extends Restlet { +public class RestResourceRestlet extends Restlet { private final Capability capability; - private final ApiServerSpec serverSpec; - private final ApiServerResourceSpec resourceSpec; + private final RestServerSpec serverSpec; + private final RestServerResourceSpec resourceSpec; private final OperationStepExecutor stepExecutor; - public ApiResourceRestlet(Capability capability, ApiServerSpec serverSpec, - ApiServerResourceSpec resourceSpec) { + public RestResourceRestlet(Capability capability, RestServerSpec serverSpec, + RestServerResourceSpec resourceSpec) { this.capability = capability; this.serverSpec = serverSpec; this.resourceSpec = resourceSpec; @@ -79,7 +80,7 @@ public void handle(Request request, Response response) { private boolean handleFromOperationSpec(Request request, Response response) { OperationStepExecutor.HandlingContext found = null; - for (ApiServerOperationSpec serverOp : getResourceSpec().getOperations()) { + for (RestServerOperationSpec serverOp : getResourceSpec().getOperations()) { if (serverOp.getMethod().equals(request.getMethod().getName())) { @@ -174,7 +175,7 @@ private boolean handleFromOperationSpec(Request request, Response response) { * Check if an operation can build a mock response using const values from outputParameters. * Returns true if the operation has at least one outputParameter with a const value. */ - private boolean canBuildMockResponse(ApiServerOperationSpec serverOp) { + private boolean canBuildMockResponse(RestServerOperationSpec serverOp) { if (serverOp.getOutputParameters() == null || serverOp.getOutputParameters().isEmpty()) { return false; } @@ -231,7 +232,7 @@ private boolean hasConstValue(OutputParameterSpec param) { /** * Send a mock response using const values from outputParameters. */ - private void sendMockResponse(ApiServerOperationSpec serverOp, Response response) { + private void sendMockResponse(RestServerOperationSpec serverOp, Response response) { try { ObjectMapper mapper = new ObjectMapper(); @@ -259,7 +260,7 @@ private void sendMockResponse(ApiServerOperationSpec serverOp, Response response /** * Build a JSON object with mock data from outputParameters const values. */ - private JsonNode buildMockData(ApiServerOperationSpec serverOp, ObjectMapper mapper) { + private JsonNode buildMockData(RestServerOperationSpec serverOp, ObjectMapper mapper) { if (serverOp.getOutputParameters() == null || serverOp.getOutputParameters().isEmpty()) { return null; } @@ -330,7 +331,7 @@ private JsonNode buildParameterValue(OutputParameterSpec param, ObjectMapper map return NullNode.instance; } - private void sendResponse(ApiServerOperationSpec serverOp, Response response, + private void sendResponse(RestServerOperationSpec serverOp, Response response, OperationStepExecutor.HandlingContext found) { // Apply output mappings if present or forward the raw entity if (serverOp.getOutputParameters() != null && !serverOp.getOutputParameters().isEmpty()) { @@ -364,7 +365,7 @@ private boolean handleFromForwardSpec(Request request, Response response) { for (ClientAdapter adapter : getCapability().getClientAdapters()) { if (adapter instanceof HttpClientAdapter) { HttpClientAdapter httpAdapter = (HttpClientAdapter) adapter; - ApiServerForwardSpec forwardSpec = getResourceSpec().getForward(); + RestServerForwardSpec forwardSpec = getResourceSpec().getForward(); if (httpAdapter.getHttpClientSpec().getNamespace() .equals(forwardSpec.getTargetNamespace())) { @@ -438,7 +439,7 @@ private void copyTrustedHeaders(Request from, Request to, Iterable trust * * Handles conversion to JSON if outputRawFormat is specified. */ - private String mapOutputParameters(ApiServerOperationSpec serverOp, + private String mapOutputParameters(RestServerOperationSpec serverOp, OperationStepExecutor.HandlingContext found) throws IOException { if (found == null || found.clientResponse == null || found.clientResponse.getEntity() == null) { @@ -476,11 +477,11 @@ public Capability getCapability() { return capability; } - public ApiServerSpec getServerSpec() { + public RestServerSpec getServerSpec() { return serverSpec; } - public ApiServerResourceSpec getResourceSpec() { + public RestServerResourceSpec getResourceSpec() { return resourceSpec; } diff --git a/src/main/java/io/naftiko/engine/exposes/ApiServerAdapter.java b/src/main/java/io/naftiko/engine/exposes/rest/RestServerAdapter.java similarity index 82% rename from src/main/java/io/naftiko/engine/exposes/ApiServerAdapter.java rename to src/main/java/io/naftiko/engine/exposes/rest/RestServerAdapter.java index 412ed0c..aceadf8 100644 --- a/src/main/java/io/naftiko/engine/exposes/ApiServerAdapter.java +++ b/src/main/java/io/naftiko/engine/exposes/rest/RestServerAdapter.java @@ -11,7 +11,7 @@ * or implied. See the License for the specific language governing permissions and limitations under * the License. */ -package io.naftiko.engine.exposes; +package io.naftiko.engine.exposes.rest; import java.nio.charset.StandardCharsets; import java.security.MessageDigest; @@ -31,31 +31,32 @@ import org.restlet.security.Verifier; import io.naftiko.Capability; import io.naftiko.engine.Resolver; -import io.naftiko.spec.consumes.AuthenticationSpec; -import io.naftiko.spec.consumes.BasicAuthenticationSpec; -import io.naftiko.spec.consumes.DigestAuthenticationSpec; +import io.naftiko.engine.exposes.ServerAdapter; +import io.naftiko.spec.consumes.http.HttpAuthenticationSpec; +import io.naftiko.spec.consumes.http.HttpBasicAuthenticationSpec; +import io.naftiko.spec.consumes.http.HttpDigestAuthenticationSpec; +import io.naftiko.spec.exposes.rest.RestServerResourceSpec; +import io.naftiko.spec.exposes.rest.RestServerSpec; import io.naftiko.spec.ExternalRefSpec; import io.naftiko.spec.ExternalRefKeysSpec; -import io.naftiko.spec.exposes.ApiServerResourceSpec; -import io.naftiko.spec.exposes.ApiServerSpec; /** * Implementation of the ServerAdapter abstract class that sets up an HTTP server using the Restlet - * Framework acting as a spec-driven API server. + * Framework acting as a spec-driven REST server. */ -public class ApiServerAdapter extends ServerAdapter { +public class RestServerAdapter extends ServerAdapter { private final Server server; private final Router router; - public ApiServerAdapter(Capability capability, ApiServerSpec serverSpec) { + public RestServerAdapter(Capability capability, RestServerSpec serverSpec) { super(capability, serverSpec); this.server = new Server(Protocol.HTTP, serverSpec.getAddress(), serverSpec.getPort()); this.router = new Router(); - for (ApiServerResourceSpec res : getApiServerSpec().getResources()) { + for (RestServerResourceSpec res : getRestServerSpec().getResources()) { String pathTemplate = toUriTemplate(res.getPath()); - Restlet resourceRestlet = new ApiResourceRestlet(capability, serverSpec, res); + Restlet resourceRestlet = new RestResourceRestlet(capability, serverSpec, res); TemplateRoute route = getRouter().attach(pathTemplate, resourceRestlet); route.getTemplate().getVariables().put("path", new Variable(Variable.TYPE_URI_PATH)); } @@ -63,9 +64,9 @@ public ApiServerAdapter(Capability capability, ApiServerSpec serverSpec) { this.server.setNext(buildServerChain(serverSpec)); } - private Restlet buildServerChain(ApiServerSpec serverSpec) { + private Restlet buildServerChain(RestServerSpec serverSpec) { Restlet next = this.router; - AuthenticationSpec authentication = serverSpec.getAuthentication(); + HttpAuthenticationSpec authentication = serverSpec.getAuthentication(); if (authentication == null || authentication.getType() == null) { return next; @@ -77,10 +78,10 @@ private Restlet buildServerChain(ApiServerSpec serverSpec) { // Extract allowed variable names from capability's external refs Set allowedVariables = extractAllowedVariables(getCapability().getSpec()); - return new ApiServerAuthenticationRestlet(authentication, next, allowedVariables); + return new RestServerAuthenticationRestlet(authentication, next, allowedVariables); } - private Restlet buildChallengeAuthenticator(AuthenticationSpec authentication, Restlet next) { + private Restlet buildChallengeAuthenticator(HttpAuthenticationSpec authentication, Restlet next) { ChallengeScheme scheme = "digest".equals(authentication.getType()) ? ChallengeScheme.HTTP_DIGEST : ChallengeScheme.HTTP_BASIC; @@ -94,10 +95,10 @@ public int verify(String identifier, char[] secret) { String expectedUsername = null; char[] expectedPassword = null; - if (authentication instanceof BasicAuthenticationSpec basic) { + if (authentication instanceof HttpBasicAuthenticationSpec basic) { expectedUsername = resolveTemplate(basic.getUsername()); expectedPassword = resolveTemplateChars(basic.getPassword()); - } else if (authentication instanceof DigestAuthenticationSpec digest) { + } else if (authentication instanceof HttpDigestAuthenticationSpec digest) { expectedUsername = resolveTemplate(digest.getUsername()); expectedPassword = resolveTemplateChars(digest.getPassword()); } @@ -161,8 +162,8 @@ private static boolean secureEquals(char[] expected, char[] actual) { new String(actual).getBytes(StandardCharsets.UTF_8)); } - public ApiServerSpec getApiServerSpec() { - return (ApiServerSpec) getSpec(); + public RestServerSpec getRestServerSpec() { + return (RestServerSpec) getSpec(); } public Server getServer() { diff --git a/src/main/java/io/naftiko/engine/exposes/ApiServerAuthenticationRestlet.java b/src/main/java/io/naftiko/engine/exposes/rest/RestServerAuthenticationRestlet.java similarity index 85% rename from src/main/java/io/naftiko/engine/exposes/ApiServerAuthenticationRestlet.java rename to src/main/java/io/naftiko/engine/exposes/rest/RestServerAuthenticationRestlet.java index 8e1e346..6531f1b 100644 --- a/src/main/java/io/naftiko/engine/exposes/ApiServerAuthenticationRestlet.java +++ b/src/main/java/io/naftiko/engine/exposes/rest/RestServerAuthenticationRestlet.java @@ -11,7 +11,7 @@ * or implied. See the License for the specific language governing permissions and limitations under * the License. */ -package io.naftiko.engine.exposes; +package io.naftiko.engine.exposes.rest; import java.nio.charset.StandardCharsets; import java.security.MessageDigest; @@ -26,27 +26,27 @@ import org.restlet.data.MediaType; import org.restlet.data.Status; import io.naftiko.engine.Resolver; -import io.naftiko.spec.consumes.ApiKeyAuthenticationSpec; -import io.naftiko.spec.consumes.AuthenticationSpec; -import io.naftiko.spec.consumes.BearerAuthenticationSpec; +import io.naftiko.spec.consumes.http.HttpApiKeyAuthenticationSpec; +import io.naftiko.spec.consumes.http.HttpAuthenticationSpec; +import io.naftiko.spec.consumes.http.HttpBearerAuthenticationSpec; /** - * Restlet responsible for API server-side authentication for bearer and apikey schemes. + * Restlet responsible for REST server-side authentication for bearer and apikey schemes. */ -public class ApiServerAuthenticationRestlet extends Restlet { +public class RestServerAuthenticationRestlet extends Restlet { private static final Pattern ENV_MUSTACHE = Pattern.compile("\\{\\{\\s*([A-Za-z0-9_\\-]+)\\s*\\}\\}"); - private final AuthenticationSpec authentication; + private final HttpAuthenticationSpec authentication; private final Restlet next; private final Set allowedVariables; - public ApiServerAuthenticationRestlet(AuthenticationSpec authentication, Restlet next) { + public RestServerAuthenticationRestlet(HttpAuthenticationSpec authentication, Restlet next) { this(authentication, next, null); } - public ApiServerAuthenticationRestlet(AuthenticationSpec authentication, Restlet next, + public RestServerAuthenticationRestlet(HttpAuthenticationSpec authentication, Restlet next, Set allowedVariables) { this.authentication = authentication; this.next = next; @@ -72,7 +72,7 @@ public void handle(Request request, Response response) { break; default: response.setStatus(Status.SERVER_ERROR_NOT_IMPLEMENTED); - response.setEntity("Unsupported API server authentication type: " + type, + response.setEntity("Unsupported REST server authentication type: " + type, MediaType.TEXT_PLAIN); return; } @@ -87,7 +87,7 @@ public void handle(Request request, Response response) { } private boolean authenticateBearer(Request request) { - if (!(authentication instanceof BearerAuthenticationSpec bearerAuth)) { + if (!(authentication instanceof HttpBearerAuthenticationSpec bearerAuth)) { return false; } @@ -116,7 +116,7 @@ private boolean authenticateBearer(Request request) { } private boolean authenticateApiKey(Request request) { - if (!(authentication instanceof ApiKeyAuthenticationSpec apiKeyAuth)) { + if (!(authentication instanceof HttpApiKeyAuthenticationSpec apiKeyAuth)) { return false; } diff --git a/src/main/java/io/naftiko/engine/exposes/SkillCatalogResource.java b/src/main/java/io/naftiko/engine/exposes/skill/SkillCatalogResource.java similarity index 93% rename from src/main/java/io/naftiko/engine/exposes/SkillCatalogResource.java rename to src/main/java/io/naftiko/engine/exposes/skill/SkillCatalogResource.java index f0133b1..7b155b7 100644 --- a/src/main/java/io/naftiko/engine/exposes/SkillCatalogResource.java +++ b/src/main/java/io/naftiko/engine/exposes/skill/SkillCatalogResource.java @@ -11,15 +11,15 @@ * or implied. See the License for the specific language governing permissions and limitations under * the License. */ -package io.naftiko.engine.exposes; +package io.naftiko.engine.exposes.skill; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; +import io.naftiko.spec.exposes.skill.ExposedSkillSpec; +import io.naftiko.spec.exposes.skill.SkillToolSpec; import org.restlet.ext.jackson.JacksonRepresentation; import org.restlet.representation.Representation; import org.restlet.resource.Get; -import io.naftiko.spec.exposes.ExposedSkillSpec; -import io.naftiko.spec.exposes.SkillToolSpec; /** * Handles {@code GET /skills} — lists all skills with their tool name summaries. diff --git a/src/main/java/io/naftiko/engine/exposes/SkillContentsResource.java b/src/main/java/io/naftiko/engine/exposes/skill/SkillContentsResource.java similarity index 96% rename from src/main/java/io/naftiko/engine/exposes/SkillContentsResource.java rename to src/main/java/io/naftiko/engine/exposes/skill/SkillContentsResource.java index 4fd4d18..0e94858 100644 --- a/src/main/java/io/naftiko/engine/exposes/SkillContentsResource.java +++ b/src/main/java/io/naftiko/engine/exposes/skill/SkillContentsResource.java @@ -11,7 +11,7 @@ * or implied. See the License for the specific language governing permissions and limitations under * the License. */ -package io.naftiko.engine.exposes; +package io.naftiko.engine.exposes.skill; import java.net.URI; import java.nio.file.Files; @@ -20,12 +20,12 @@ import java.util.stream.Stream; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; +import io.naftiko.spec.exposes.skill.ExposedSkillSpec; import org.restlet.ext.jackson.JacksonRepresentation; import org.restlet.data.Status; import org.restlet.representation.Representation; import org.restlet.resource.Get; import org.restlet.resource.ResourceException; -import io.naftiko.spec.exposes.ExposedSkillSpec; /** * Handles {@code GET /skills/{name}/contents} — lists all files in the skill's {@code location} diff --git a/src/main/java/io/naftiko/engine/exposes/SkillDetailResource.java b/src/main/java/io/naftiko/engine/exposes/skill/SkillDetailResource.java similarity index 96% rename from src/main/java/io/naftiko/engine/exposes/SkillDetailResource.java rename to src/main/java/io/naftiko/engine/exposes/skill/SkillDetailResource.java index af7724b..60b546f 100644 --- a/src/main/java/io/naftiko/engine/exposes/SkillDetailResource.java +++ b/src/main/java/io/naftiko/engine/exposes/skill/SkillDetailResource.java @@ -11,18 +11,18 @@ * or implied. See the License for the specific language governing permissions and limitations under * the License. */ -package io.naftiko.engine.exposes; +package io.naftiko.engine.exposes.skill; import java.util.Map; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; +import io.naftiko.spec.exposes.skill.ExposedSkillSpec; +import io.naftiko.spec.exposes.skill.SkillToolSpec; import org.restlet.ext.jackson.JacksonRepresentation; import org.restlet.data.Status; import org.restlet.representation.Representation; import org.restlet.resource.Get; import org.restlet.resource.ResourceException; -import io.naftiko.spec.exposes.ExposedSkillSpec; -import io.naftiko.spec.exposes.SkillToolSpec; /** * Handles {@code GET /skills/{name}} — returns full skill metadata and tool catalog. diff --git a/src/main/java/io/naftiko/engine/exposes/SkillDownloadResource.java b/src/main/java/io/naftiko/engine/exposes/skill/SkillDownloadResource.java similarity index 97% rename from src/main/java/io/naftiko/engine/exposes/SkillDownloadResource.java rename to src/main/java/io/naftiko/engine/exposes/skill/SkillDownloadResource.java index 9baa3c5..e961c22 100644 --- a/src/main/java/io/naftiko/engine/exposes/SkillDownloadResource.java +++ b/src/main/java/io/naftiko/engine/exposes/skill/SkillDownloadResource.java @@ -11,7 +11,7 @@ * or implied. See the License for the specific language governing permissions and limitations under * the License. */ -package io.naftiko.engine.exposes; +package io.naftiko.engine.exposes.skill; import java.io.IOException; import java.io.OutputStream; @@ -30,7 +30,7 @@ import org.restlet.representation.Representation; import org.restlet.resource.Get; import org.restlet.resource.ResourceException; -import io.naftiko.spec.exposes.ExposedSkillSpec; +import io.naftiko.spec.exposes.skill.ExposedSkillSpec; /** * Handles {@code GET /skills/{name}/download} — streams a ZIP archive of the skill's diff --git a/src/main/java/io/naftiko/engine/exposes/SkillFileResource.java b/src/main/java/io/naftiko/engine/exposes/skill/SkillFileResource.java similarity index 96% rename from src/main/java/io/naftiko/engine/exposes/SkillFileResource.java rename to src/main/java/io/naftiko/engine/exposes/skill/SkillFileResource.java index 9e8ae21..9f026f2 100644 --- a/src/main/java/io/naftiko/engine/exposes/SkillFileResource.java +++ b/src/main/java/io/naftiko/engine/exposes/skill/SkillFileResource.java @@ -11,7 +11,7 @@ * or implied. See the License for the specific language governing permissions and limitations under * the License. */ -package io.naftiko.engine.exposes; +package io.naftiko.engine.exposes.skill; import java.nio.file.Files; import java.nio.file.Path; @@ -21,7 +21,7 @@ import org.restlet.representation.Representation; import org.restlet.resource.Get; import org.restlet.resource.ResourceException; -import io.naftiko.spec.exposes.ExposedSkillSpec; +import io.naftiko.spec.exposes.skill.ExposedSkillSpec; /** * Handles {@code GET /skills/{name}/contents/{file}} — serves an individual file from the skill's diff --git a/src/main/java/io/naftiko/engine/exposes/SkillServerAdapter.java b/src/main/java/io/naftiko/engine/exposes/skill/SkillServerAdapter.java similarity index 91% rename from src/main/java/io/naftiko/engine/exposes/SkillServerAdapter.java rename to src/main/java/io/naftiko/engine/exposes/skill/SkillServerAdapter.java index 88291c0..f104bb9 100644 --- a/src/main/java/io/naftiko/engine/exposes/SkillServerAdapter.java +++ b/src/main/java/io/naftiko/engine/exposes/skill/SkillServerAdapter.java @@ -11,7 +11,7 @@ * or implied. See the License for the specific language governing permissions and limitations under * the License. */ -package io.naftiko.engine.exposes; +package io.naftiko.engine.exposes.skill; import java.util.HashMap; import java.util.Map; @@ -23,12 +23,13 @@ import org.restlet.routing.TemplateRoute; import org.restlet.routing.Variable; import io.naftiko.Capability; -import io.naftiko.spec.exposes.ApiServerSpec; -import io.naftiko.spec.exposes.ExposedSkillSpec; -import io.naftiko.spec.exposes.McpServerSpec; +import io.naftiko.engine.exposes.ServerAdapter; import io.naftiko.spec.exposes.ServerSpec; -import io.naftiko.spec.exposes.SkillServerSpec; -import io.naftiko.spec.exposes.SkillToolSpec; +import io.naftiko.spec.exposes.mcp.McpServerSpec; +import io.naftiko.spec.exposes.rest.RestServerSpec; +import io.naftiko.spec.exposes.skill.ExposedSkillSpec; +import io.naftiko.spec.exposes.skill.SkillServerSpec; +import io.naftiko.spec.exposes.skill.SkillToolSpec; /** * Skill Server Adapter — exposes a read-only catalog of agent skills over predefined HTTP @@ -44,7 +45,7 @@ * * *

At construction time the adapter validates that every tool in every skill either references a - * sibling {@code api}/{@code mcp} namespace (via {@code from}) or points to an instruction file + * sibling {@code rest}/{@code mcp} namespace (via {@code from}) or points to an instruction file * (via {@code instruction}) — never both and never neither.

*/ public class SkillServerAdapter extends ServerAdapter { @@ -76,7 +77,7 @@ public SkillServerAdapter(Capability capability, SkillServerSpec serverSpec) { } /** - * Builds a lookup map from namespace name to adapter type ({@code "api"} or {@code "mcp"}) + * Builds a lookup map from namespace name to adapter type ({@code "rest"} or {@code "mcp"}) * by scanning the sibling {@link ServerSpec} entries in the capability. The skill adapter * itself is excluded. */ @@ -87,10 +88,10 @@ private static Map buildNamespaceMode(Capability capability, if (spec == selfSpec) { continue; } - if (spec instanceof ApiServerSpec) { - String ns = ((ApiServerSpec) spec).getNamespace(); + if (spec instanceof RestServerSpec) { + String ns = ((RestServerSpec) spec).getNamespace(); if (ns != null) { - map.put(ns, "api"); + map.put(ns, "rest"); } } else if (spec instanceof McpServerSpec) { String ns = ((McpServerSpec) spec).getNamespace(); diff --git a/src/main/java/io/naftiko/engine/exposes/SkillServerResource.java b/src/main/java/io/naftiko/engine/exposes/skill/SkillServerResource.java similarity index 96% rename from src/main/java/io/naftiko/engine/exposes/SkillServerResource.java rename to src/main/java/io/naftiko/engine/exposes/skill/SkillServerResource.java index 4dc6ecc..4cc22f2 100644 --- a/src/main/java/io/naftiko/engine/exposes/SkillServerResource.java +++ b/src/main/java/io/naftiko/engine/exposes/skill/SkillServerResource.java @@ -11,7 +11,7 @@ * or implied. See the License for the specific language governing permissions and limitations under * the License. */ -package io.naftiko.engine.exposes; +package io.naftiko.engine.exposes.skill; import java.net.URI; import java.nio.file.Path; @@ -19,11 +19,11 @@ import java.util.Map; import java.util.regex.Pattern; import com.fasterxml.jackson.databind.ObjectMapper; +import io.naftiko.spec.exposes.skill.ExposedSkillSpec; +import io.naftiko.spec.exposes.skill.SkillServerSpec; import org.restlet.data.MediaType; import org.restlet.resource.ServerResource; import org.restlet.service.MetadataService; -import io.naftiko.spec.exposes.ExposedSkillSpec; -import io.naftiko.spec.exposes.SkillServerSpec; /** * Abstract base for all skill server handler resources. diff --git a/src/main/java/io/naftiko/spec/consumes/ClientSpec.java b/src/main/java/io/naftiko/spec/consumes/ClientSpec.java index c595910..16192a7 100644 --- a/src/main/java/io/naftiko/spec/consumes/ClientSpec.java +++ b/src/main/java/io/naftiko/spec/consumes/ClientSpec.java @@ -16,6 +16,7 @@ import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonSubTypes; import com.fasterxml.jackson.annotation.JsonTypeInfo; +import io.naftiko.spec.consumes.http.HttpClientSpec; /** * Base Exposed Adapter Specification Element diff --git a/src/main/java/io/naftiko/spec/consumes/ApiKeyAuthenticationSpec.java b/src/main/java/io/naftiko/spec/consumes/http/HttpApiKeyAuthenticationSpec.java similarity index 84% rename from src/main/java/io/naftiko/spec/consumes/ApiKeyAuthenticationSpec.java rename to src/main/java/io/naftiko/spec/consumes/http/HttpApiKeyAuthenticationSpec.java index 942986d..3716172 100644 --- a/src/main/java/io/naftiko/spec/consumes/ApiKeyAuthenticationSpec.java +++ b/src/main/java/io/naftiko/spec/consumes/http/HttpApiKeyAuthenticationSpec.java @@ -11,22 +11,22 @@ * or implied. See the License for the specific language governing permissions and limitations under * the License. */ -package io.naftiko.spec.consumes; +package io.naftiko.spec.consumes.http; /** * API Key Authentication Specification Element */ -public class ApiKeyAuthenticationSpec extends AuthenticationSpec { +public class HttpApiKeyAuthenticationSpec extends HttpAuthenticationSpec { private volatile String key; private volatile String placement; private volatile String value; - public ApiKeyAuthenticationSpec() { + public HttpApiKeyAuthenticationSpec() { this(null, null, null); } - public ApiKeyAuthenticationSpec(String key, String placement, String value) { + public HttpApiKeyAuthenticationSpec(String key, String placement, String value) { super("apikey"); this.key = key; this.placement = placement; diff --git a/src/main/java/io/naftiko/spec/consumes/AuthenticationSpec.java b/src/main/java/io/naftiko/spec/consumes/http/HttpAuthenticationSpec.java similarity index 70% rename from src/main/java/io/naftiko/spec/consumes/AuthenticationSpec.java rename to src/main/java/io/naftiko/spec/consumes/http/HttpAuthenticationSpec.java index d7662a8..21a3e5f 100644 --- a/src/main/java/io/naftiko/spec/consumes/AuthenticationSpec.java +++ b/src/main/java/io/naftiko/spec/consumes/http/HttpAuthenticationSpec.java @@ -11,7 +11,7 @@ * or implied. See the License for the specific language governing permissions and limitations under * the License. */ -package io.naftiko.spec.consumes; +package io.naftiko.spec.consumes.http; import com.fasterxml.jackson.annotation.JsonSubTypes; import com.fasterxml.jackson.annotation.JsonTypeInfo; @@ -25,20 +25,20 @@ property = "type" // The name of the JSON property holding the type identifier ) @JsonSubTypes({ - @JsonSubTypes.Type(value = ApiKeyAuthenticationSpec.class, name = "apikey"), - @JsonSubTypes.Type(value = BasicAuthenticationSpec.class, name = "basic"), - @JsonSubTypes.Type(value = BearerAuthenticationSpec.class, name = "bearer"), - @JsonSubTypes.Type(value = DigestAuthenticationSpec.class, name = "digest") + @JsonSubTypes.Type(value = HttpApiKeyAuthenticationSpec.class, name = "apikey"), + @JsonSubTypes.Type(value = HttpBasicAuthenticationSpec.class, name = "basic"), + @JsonSubTypes.Type(value = HttpBearerAuthenticationSpec.class, name = "bearer"), + @JsonSubTypes.Type(value = HttpDigestAuthenticationSpec.class, name = "digest") }) -public abstract class AuthenticationSpec { +public abstract class HttpAuthenticationSpec { private volatile String type; - public AuthenticationSpec() { + public HttpAuthenticationSpec() { this(null); } - public AuthenticationSpec(String type) { + public HttpAuthenticationSpec(String type) { this.type = type; } diff --git a/src/main/java/io/naftiko/spec/consumes/BasicAuthenticationSpec.java b/src/main/java/io/naftiko/spec/consumes/http/HttpBasicAuthenticationSpec.java similarity index 83% rename from src/main/java/io/naftiko/spec/consumes/BasicAuthenticationSpec.java rename to src/main/java/io/naftiko/spec/consumes/http/HttpBasicAuthenticationSpec.java index 285d639..b941cb4 100644 --- a/src/main/java/io/naftiko/spec/consumes/BasicAuthenticationSpec.java +++ b/src/main/java/io/naftiko/spec/consumes/http/HttpBasicAuthenticationSpec.java @@ -11,21 +11,21 @@ * or implied. See the License for the specific language governing permissions and limitations under * the License. */ -package io.naftiko.spec.consumes; +package io.naftiko.spec.consumes.http; /** * HTTP Basic Authentication Specification Element */ -public class BasicAuthenticationSpec extends AuthenticationSpec { +public class HttpBasicAuthenticationSpec extends HttpAuthenticationSpec { private volatile String username; private volatile char[] password; - public BasicAuthenticationSpec() { + public HttpBasicAuthenticationSpec() { this(null, null); } - public BasicAuthenticationSpec(String username, char[] password) { + public HttpBasicAuthenticationSpec(String username, char[] password) { super("basic"); this.username = username; this.password = password; diff --git a/src/main/java/io/naftiko/spec/consumes/BearerAuthenticationSpec.java b/src/main/java/io/naftiko/spec/consumes/http/HttpBearerAuthenticationSpec.java similarity index 81% rename from src/main/java/io/naftiko/spec/consumes/BearerAuthenticationSpec.java rename to src/main/java/io/naftiko/spec/consumes/http/HttpBearerAuthenticationSpec.java index 3568544..64343a3 100644 --- a/src/main/java/io/naftiko/spec/consumes/BearerAuthenticationSpec.java +++ b/src/main/java/io/naftiko/spec/consumes/http/HttpBearerAuthenticationSpec.java @@ -11,20 +11,20 @@ * or implied. See the License for the specific language governing permissions and limitations under * the License. */ -package io.naftiko.spec.consumes; +package io.naftiko.spec.consumes.http; /** * OAuth Bearer Token Authentication Specification Element */ -public class BearerAuthenticationSpec extends AuthenticationSpec { +public class HttpBearerAuthenticationSpec extends HttpAuthenticationSpec { private volatile String token; - public BearerAuthenticationSpec() { + public HttpBearerAuthenticationSpec() { this(null); } - public BearerAuthenticationSpec(String token) { + public HttpBearerAuthenticationSpec(String token) { super("bearer"); this.token = token; } diff --git a/src/main/java/io/naftiko/spec/consumes/HttpClientOperationSpec.java b/src/main/java/io/naftiko/spec/consumes/http/HttpClientOperationSpec.java similarity index 97% rename from src/main/java/io/naftiko/spec/consumes/HttpClientOperationSpec.java rename to src/main/java/io/naftiko/spec/consumes/http/HttpClientOperationSpec.java index 4483cc4..e19e6ac 100644 --- a/src/main/java/io/naftiko/spec/consumes/HttpClientOperationSpec.java +++ b/src/main/java/io/naftiko/spec/consumes/http/HttpClientOperationSpec.java @@ -11,7 +11,7 @@ * or implied. See the License for the specific language governing permissions and limitations under * the License. */ -package io.naftiko.spec.consumes; +package io.naftiko.spec.consumes.http; import io.naftiko.spec.OperationSpec; diff --git a/src/main/java/io/naftiko/spec/consumes/HttpClientResourceSpec.java b/src/main/java/io/naftiko/spec/consumes/http/HttpClientResourceSpec.java similarity index 98% rename from src/main/java/io/naftiko/spec/consumes/HttpClientResourceSpec.java rename to src/main/java/io/naftiko/spec/consumes/http/HttpClientResourceSpec.java index 8e50379..293dc96 100644 --- a/src/main/java/io/naftiko/spec/consumes/HttpClientResourceSpec.java +++ b/src/main/java/io/naftiko/spec/consumes/http/HttpClientResourceSpec.java @@ -11,7 +11,7 @@ * or implied. See the License for the specific language governing permissions and limitations under * the License. */ -package io.naftiko.spec.consumes; +package io.naftiko.spec.consumes.http; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; diff --git a/src/main/java/io/naftiko/spec/consumes/HttpClientSpec.java b/src/main/java/io/naftiko/spec/consumes/http/HttpClientSpec.java similarity index 84% rename from src/main/java/io/naftiko/spec/consumes/HttpClientSpec.java rename to src/main/java/io/naftiko/spec/consumes/http/HttpClientSpec.java index 14535ef..2ec5f66 100644 --- a/src/main/java/io/naftiko/spec/consumes/HttpClientSpec.java +++ b/src/main/java/io/naftiko/spec/consumes/http/HttpClientSpec.java @@ -11,12 +11,13 @@ * or implied. See the License for the specific language governing permissions and limitations under * the License. */ -package io.naftiko.spec.consumes; +package io.naftiko.spec.consumes.http; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; import com.fasterxml.jackson.annotation.JsonInclude; import io.naftiko.spec.InputParameterSpec; +import io.naftiko.spec.consumes.ClientSpec; /** * Specification Element of consumed HTTP adapter endpoints @@ -29,12 +30,12 @@ public class HttpClientSpec extends ClientSpec { private final List inputParameters; @JsonInclude(JsonInclude.Include.NON_NULL) - private volatile AuthenticationSpec authentication; + private volatile HttpAuthenticationSpec authentication; @JsonInclude(JsonInclude.Include.NON_EMPTY) private List resources; - public HttpClientSpec(String namespace, String baseUri, AuthenticationSpec authentication) { + public HttpClientSpec(String namespace, String baseUri, HttpAuthenticationSpec authentication) { super("http", namespace); this.baseUri = baseUri; this.inputParameters = new CopyOnWriteArrayList<>(); @@ -62,11 +63,11 @@ public List getInputParameters() { return inputParameters; } - public AuthenticationSpec getAuthentication() { + public HttpAuthenticationSpec getAuthentication() { return authentication; } - public void setAuthentication(AuthenticationSpec authentication) { + public void setAuthentication(HttpAuthenticationSpec authentication) { this.authentication = authentication; } diff --git a/src/main/java/io/naftiko/spec/consumes/DigestAuthenticationSpec.java b/src/main/java/io/naftiko/spec/consumes/http/HttpDigestAuthenticationSpec.java similarity index 83% rename from src/main/java/io/naftiko/spec/consumes/DigestAuthenticationSpec.java rename to src/main/java/io/naftiko/spec/consumes/http/HttpDigestAuthenticationSpec.java index 0f64d8b..8e4c726 100644 --- a/src/main/java/io/naftiko/spec/consumes/DigestAuthenticationSpec.java +++ b/src/main/java/io/naftiko/spec/consumes/http/HttpDigestAuthenticationSpec.java @@ -11,21 +11,21 @@ * or implied. See the License for the specific language governing permissions and limitations under * the License. */ -package io.naftiko.spec.consumes; +package io.naftiko.spec.consumes.http; /** * HTTP Digest Authentication Specification Element */ -public class DigestAuthenticationSpec extends AuthenticationSpec { +public class HttpDigestAuthenticationSpec extends HttpAuthenticationSpec { private volatile String username; private volatile char[] password; - public DigestAuthenticationSpec() { + public HttpDigestAuthenticationSpec() { this(null, null); } - public DigestAuthenticationSpec(String username, char[] password) { + public HttpDigestAuthenticationSpec(String username, char[] password) { super("digest"); this.username = username; this.password = password; diff --git a/src/main/java/io/naftiko/spec/exposes/ServerSpec.java b/src/main/java/io/naftiko/spec/exposes/ServerSpec.java index d45cda0..1cb63bf 100644 --- a/src/main/java/io/naftiko/spec/exposes/ServerSpec.java +++ b/src/main/java/io/naftiko/spec/exposes/ServerSpec.java @@ -19,6 +19,9 @@ import com.fasterxml.jackson.annotation.JsonSubTypes; import com.fasterxml.jackson.annotation.JsonTypeInfo; import io.naftiko.spec.InputParameterSpec; +import io.naftiko.spec.exposes.mcp.McpServerSpec; +import io.naftiko.spec.exposes.rest.RestServerSpec; +import io.naftiko.spec.exposes.skill.SkillServerSpec; /** * Base Exposed Adapter Specification Element @@ -29,7 +32,7 @@ property = "type" // The name of the JSON property holding the type identifier ) @JsonSubTypes({ - @JsonSubTypes.Type(value = ApiServerSpec.class, name = "api"), + @JsonSubTypes.Type(value = RestServerSpec.class, name = "rest"), @JsonSubTypes.Type(value = McpServerSpec.class, name = "mcp"), @JsonSubTypes.Type(value = SkillServerSpec.class, name = "skill") }) diff --git a/src/main/java/io/naftiko/spec/exposes/McpPromptArgumentSpec.java b/src/main/java/io/naftiko/spec/exposes/mcp/McpPromptArgumentSpec.java similarity index 98% rename from src/main/java/io/naftiko/spec/exposes/McpPromptArgumentSpec.java rename to src/main/java/io/naftiko/spec/exposes/mcp/McpPromptArgumentSpec.java index 7cc2ce2..b18c125 100644 --- a/src/main/java/io/naftiko/spec/exposes/McpPromptArgumentSpec.java +++ b/src/main/java/io/naftiko/spec/exposes/mcp/McpPromptArgumentSpec.java @@ -11,7 +11,7 @@ * or implied. See the License for the specific language governing permissions and limitations under * the License. */ -package io.naftiko.spec.exposes; +package io.naftiko.spec.exposes.mcp; import com.fasterxml.jackson.annotation.JsonInclude; diff --git a/src/main/java/io/naftiko/spec/exposes/McpPromptMessageSpec.java b/src/main/java/io/naftiko/spec/exposes/mcp/McpPromptMessageSpec.java similarity index 97% rename from src/main/java/io/naftiko/spec/exposes/McpPromptMessageSpec.java rename to src/main/java/io/naftiko/spec/exposes/mcp/McpPromptMessageSpec.java index e78ce71..5e08fd7 100644 --- a/src/main/java/io/naftiko/spec/exposes/McpPromptMessageSpec.java +++ b/src/main/java/io/naftiko/spec/exposes/mcp/McpPromptMessageSpec.java @@ -11,7 +11,7 @@ * or implied. See the License for the specific language governing permissions and limitations under * the License. */ -package io.naftiko.spec.exposes; +package io.naftiko.spec.exposes.mcp; /** * A single message in an inline MCP prompt template. diff --git a/src/main/java/io/naftiko/spec/exposes/McpServerPromptSpec.java b/src/main/java/io/naftiko/spec/exposes/mcp/McpServerPromptSpec.java similarity index 98% rename from src/main/java/io/naftiko/spec/exposes/McpServerPromptSpec.java rename to src/main/java/io/naftiko/spec/exposes/mcp/McpServerPromptSpec.java index dc14974..af6bf30 100644 --- a/src/main/java/io/naftiko/spec/exposes/McpServerPromptSpec.java +++ b/src/main/java/io/naftiko/spec/exposes/mcp/McpServerPromptSpec.java @@ -11,7 +11,7 @@ * or implied. See the License for the specific language governing permissions and limitations under * the License. */ -package io.naftiko.spec.exposes; +package io.naftiko.spec.exposes.mcp; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; diff --git a/src/main/java/io/naftiko/spec/exposes/McpServerResourceSpec.java b/src/main/java/io/naftiko/spec/exposes/mcp/McpServerResourceSpec.java similarity index 96% rename from src/main/java/io/naftiko/spec/exposes/McpServerResourceSpec.java rename to src/main/java/io/naftiko/spec/exposes/mcp/McpServerResourceSpec.java index e8b9d25..dec7047 100644 --- a/src/main/java/io/naftiko/spec/exposes/McpServerResourceSpec.java +++ b/src/main/java/io/naftiko/spec/exposes/mcp/McpServerResourceSpec.java @@ -11,7 +11,7 @@ * or implied. See the License for the specific language governing permissions and limitations under * the License. */ -package io.naftiko.spec.exposes; +package io.naftiko.spec.exposes.mcp; import java.util.List; import java.util.Map; @@ -19,6 +19,8 @@ import java.util.concurrent.ConcurrentHashMap; import com.fasterxml.jackson.annotation.JsonInclude; import io.naftiko.spec.OutputParameterSpec; +import io.naftiko.spec.exposes.OperationStepSpec; +import io.naftiko.spec.exposes.ServerCallSpec; /** * MCP Resource Specification Element. diff --git a/src/main/java/io/naftiko/spec/exposes/McpServerSpec.java b/src/main/java/io/naftiko/spec/exposes/mcp/McpServerSpec.java similarity index 97% rename from src/main/java/io/naftiko/spec/exposes/McpServerSpec.java rename to src/main/java/io/naftiko/spec/exposes/mcp/McpServerSpec.java index 5e9761a..5dcc8be 100644 --- a/src/main/java/io/naftiko/spec/exposes/McpServerSpec.java +++ b/src/main/java/io/naftiko/spec/exposes/mcp/McpServerSpec.java @@ -11,11 +11,12 @@ * or implied. See the License for the specific language governing permissions and limitations under * the License. */ -package io.naftiko.spec.exposes; +package io.naftiko.spec.exposes.mcp; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; import com.fasterxml.jackson.annotation.JsonInclude; +import io.naftiko.spec.exposes.ServerSpec; /** * MCP Server Specification Element. diff --git a/src/main/java/io/naftiko/spec/exposes/McpServerToolSpec.java b/src/main/java/io/naftiko/spec/exposes/mcp/McpServerToolSpec.java similarity index 96% rename from src/main/java/io/naftiko/spec/exposes/McpServerToolSpec.java rename to src/main/java/io/naftiko/spec/exposes/mcp/McpServerToolSpec.java index 507ac35..dfd28ae 100644 --- a/src/main/java/io/naftiko/spec/exposes/McpServerToolSpec.java +++ b/src/main/java/io/naftiko/spec/exposes/mcp/McpServerToolSpec.java @@ -11,7 +11,7 @@ * or implied. See the License for the specific language governing permissions and limitations under * the License. */ -package io.naftiko.spec.exposes; +package io.naftiko.spec.exposes.mcp; import java.util.List; import java.util.Map; @@ -20,6 +20,8 @@ import com.fasterxml.jackson.annotation.JsonInclude; import io.naftiko.spec.InputParameterSpec; import io.naftiko.spec.OutputParameterSpec; +import io.naftiko.spec.exposes.OperationStepSpec; +import io.naftiko.spec.exposes.ServerCallSpec; /** * MCP Tool Specification Element. diff --git a/src/main/java/io/naftiko/spec/exposes/ApiServerForwardSpec.java b/src/main/java/io/naftiko/spec/exposes/rest/RestServerForwardSpec.java similarity index 87% rename from src/main/java/io/naftiko/spec/exposes/ApiServerForwardSpec.java rename to src/main/java/io/naftiko/spec/exposes/rest/RestServerForwardSpec.java index 25a57d0..cd5894b 100644 --- a/src/main/java/io/naftiko/spec/exposes/ApiServerForwardSpec.java +++ b/src/main/java/io/naftiko/spec/exposes/rest/RestServerForwardSpec.java @@ -11,7 +11,7 @@ * or implied. See the License for the specific language governing permissions and limitations under * the License. */ -package io.naftiko.spec.exposes; +package io.naftiko.spec.exposes.rest; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; @@ -19,17 +19,17 @@ /** * Specification Element for forwarding trusted headers */ -public class ApiServerForwardSpec { +public class RestServerForwardSpec { private volatile String targetNamespace; private final List trustedHeaders; - public ApiServerForwardSpec() { + public RestServerForwardSpec() { this(null); } - public ApiServerForwardSpec(String targetNamespace) { + public RestServerForwardSpec(String targetNamespace) { this.targetNamespace = targetNamespace; this.trustedHeaders = new CopyOnWriteArrayList<>(); } diff --git a/src/main/java/io/naftiko/spec/exposes/ApiServerOperationSpec.java b/src/main/java/io/naftiko/spec/exposes/rest/RestServerOperationSpec.java similarity index 68% rename from src/main/java/io/naftiko/spec/exposes/ApiServerOperationSpec.java rename to src/main/java/io/naftiko/spec/exposes/rest/RestServerOperationSpec.java index a7ed2f3..be4091a 100644 --- a/src/main/java/io/naftiko/spec/exposes/ApiServerOperationSpec.java +++ b/src/main/java/io/naftiko/spec/exposes/rest/RestServerOperationSpec.java @@ -11,7 +11,7 @@ * or implied. See the License for the specific language governing permissions and limitations under * the License. */ -package io.naftiko.spec.exposes; +package io.naftiko.spec.exposes.rest; import java.util.List; import java.util.Map; @@ -19,11 +19,13 @@ import java.util.concurrent.ConcurrentHashMap; import com.fasterxml.jackson.annotation.JsonInclude; import io.naftiko.spec.OperationSpec; +import io.naftiko.spec.exposes.OperationStepSpec; +import io.naftiko.spec.exposes.ServerCallSpec; /** - * API Operation Specification Element + * REST Operation Specification Element */ -public class ApiServerOperationSpec extends OperationSpec { +public class RestServerOperationSpec extends OperationSpec { @JsonInclude(JsonInclude.Include.NON_NULL) private volatile ServerCallSpec call; @@ -34,23 +36,23 @@ public class ApiServerOperationSpec extends OperationSpec { @JsonInclude(JsonInclude.Include.NON_NULL) private volatile Map with; - public ApiServerOperationSpec() { + public RestServerOperationSpec() { this(null, null, null, null, null, null, null, null, null); } - public ApiServerOperationSpec(ApiServerResourceSpec parentResource, String method, String name, String label) { + public RestServerOperationSpec(RestServerResourceSpec parentResource, String method, String name, String label) { this(parentResource, method, name, label, null, null, null, null, null); } - public ApiServerOperationSpec(ApiServerResourceSpec parentResource, String method, String name, String label, String description, String outputRawFormat, ServerCallSpec call) { + public RestServerOperationSpec(RestServerResourceSpec parentResource, String method, String name, String label, String description, String outputRawFormat, ServerCallSpec call) { this(parentResource, method, name, label, description, outputRawFormat, null, call, null); } - public ApiServerOperationSpec(ApiServerResourceSpec parentResource, String method, String name, String label, String description, String outputRawFormat, String outputSchema, ServerCallSpec call) { + public RestServerOperationSpec(RestServerResourceSpec parentResource, String method, String name, String label, String description, String outputRawFormat, String outputSchema, ServerCallSpec call) { this(parentResource, method, name, label, description, outputRawFormat, outputSchema, call, null); } - public ApiServerOperationSpec(ApiServerResourceSpec parentResource, String method, String name, String label, String description, String outputRawFormat, String outputSchema, ServerCallSpec call, Map with) { + public RestServerOperationSpec(RestServerResourceSpec parentResource, String method, String name, String label, String description, String outputRawFormat, String outputSchema, ServerCallSpec call, Map with) { super(parentResource, method, name, label, description, outputRawFormat, outputSchema); this.call = call; this.with = with != null ? new ConcurrentHashMap<>(with) : null; diff --git a/src/main/java/io/naftiko/spec/exposes/ApiServerResourceSpec.java b/src/main/java/io/naftiko/spec/exposes/rest/RestServerResourceSpec.java similarity index 64% rename from src/main/java/io/naftiko/spec/exposes/ApiServerResourceSpec.java rename to src/main/java/io/naftiko/spec/exposes/rest/RestServerResourceSpec.java index 3394f84..4607483 100644 --- a/src/main/java/io/naftiko/spec/exposes/ApiServerResourceSpec.java +++ b/src/main/java/io/naftiko/spec/exposes/rest/RestServerResourceSpec.java @@ -11,7 +11,7 @@ * or implied. See the License for the specific language governing permissions and limitations under * the License. */ -package io.naftiko.spec.exposes; +package io.naftiko.spec.exposes.rest; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; @@ -20,54 +20,54 @@ import io.naftiko.spec.ResourceSpec; /** - * API Resource Specification Element + * REST Resource Specification Element */ -public class ApiServerResourceSpec extends ResourceSpec { +public class RestServerResourceSpec extends ResourceSpec { @JsonInclude(JsonInclude.Include.NON_EMPTY) - private volatile List operations; + private volatile List operations; - private volatile ApiServerForwardSpec forward; + private volatile RestServerForwardSpec forward; - public ApiServerResourceSpec() { + public RestServerResourceSpec() { this(null, null, null, null, null); } - public ApiServerResourceSpec(String path) { + public RestServerResourceSpec(String path) { this(path, null, null, null, null); } - public ApiServerResourceSpec(String path, String name, String label, String description, ApiServerForwardSpec forward) { + public RestServerResourceSpec(String path, String name, String label, String description, RestServerForwardSpec forward) { super(path, name, label, description); this.operations = new CopyOnWriteArrayList<>(); this.forward = forward; } - public List getOperations() { + public List getOperations() { return operations; } /** * Sets operations and establishes parent resource reference for each operation. - * This ensures that each ApiOperationSpec knows its parent ResourceSpec. + * This ensures that each RestOperationSpec knows its parent ResourceSpec. * * @JsonSetter ensures this method is called by Jackson during deserialization */ @JsonSetter - public void setOperations(List operations) { + public void setOperations(List operations) { this.operations = operations; if (operations != null) { - for (ApiServerOperationSpec operation : operations) { + for (RestServerOperationSpec operation : operations) { operation.setParentResource(this); } } } - public ApiServerForwardSpec getForward() { + public RestServerForwardSpec getForward() { return forward; } - public void setForward(ApiServerForwardSpec forward) { + public void setForward(RestServerForwardSpec forward) { this.forward = forward; } diff --git a/src/main/java/io/naftiko/spec/exposes/ApiServerSpec.java b/src/main/java/io/naftiko/spec/exposes/rest/RestServerSpec.java similarity index 66% rename from src/main/java/io/naftiko/spec/exposes/ApiServerSpec.java rename to src/main/java/io/naftiko/spec/exposes/rest/RestServerSpec.java index acd5783..35ee6d6 100644 --- a/src/main/java/io/naftiko/spec/exposes/ApiServerSpec.java +++ b/src/main/java/io/naftiko/spec/exposes/rest/RestServerSpec.java @@ -11,33 +11,34 @@ * or implied. See the License for the specific language governing permissions and limitations under * the License. */ -package io.naftiko.spec.exposes; +package io.naftiko.spec.exposes.rest; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; import com.fasterxml.jackson.annotation.JsonInclude; -import io.naftiko.spec.consumes.AuthenticationSpec; +import io.naftiko.spec.consumes.http.HttpAuthenticationSpec; +import io.naftiko.spec.exposes.ServerSpec; /** - * Web API Server Specification Element + * REST Server Specification Element */ -public class ApiServerSpec extends ServerSpec { +public class RestServerSpec extends ServerSpec { @JsonInclude(JsonInclude.Include.NON_NULL) private volatile String namespace; @JsonInclude(JsonInclude.Include.NON_EMPTY) - private final List resources; + private final List resources; @JsonInclude(JsonInclude.Include.NON_NULL) - private volatile AuthenticationSpec authentication; + private volatile HttpAuthenticationSpec authentication; - public ApiServerSpec() { + public RestServerSpec() { this(null, 0, null); } - public ApiServerSpec(String address, int port, String namespace) { - super("api", address, port); + public RestServerSpec(String address, int port, String namespace) { + super("rest", address, port); this.namespace = namespace; this.resources = new CopyOnWriteArrayList<>(); } @@ -50,15 +51,15 @@ public void setNamespace(String namespace) { this.namespace = namespace; } - public List getResources() { + public List getResources() { return resources; } - public AuthenticationSpec getAuthentication() { + public HttpAuthenticationSpec getAuthentication() { return authentication; } - public void setAuthentication(AuthenticationSpec authentication) { + public void setAuthentication(HttpAuthenticationSpec authentication) { this.authentication = authentication; } diff --git a/src/main/java/io/naftiko/spec/exposes/ApiServerStepSpec.java b/src/main/java/io/naftiko/spec/exposes/rest/RestServerStepSpec.java similarity index 79% rename from src/main/java/io/naftiko/spec/exposes/ApiServerStepSpec.java rename to src/main/java/io/naftiko/spec/exposes/rest/RestServerStepSpec.java index bfdb36b..644a4d6 100644 --- a/src/main/java/io/naftiko/spec/exposes/ApiServerStepSpec.java +++ b/src/main/java/io/naftiko/spec/exposes/rest/RestServerStepSpec.java @@ -11,20 +11,21 @@ * or implied. See the License for the specific language governing permissions and limitations under * the License. */ -package io.naftiko.spec.exposes; +package io.naftiko.spec.exposes.rest; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import com.fasterxml.jackson.annotation.JsonInclude; +import io.naftiko.spec.exposes.ServerCallSpec; /** - * API Operation Step Specification Element + * REST Operation Step Specification Element * - * Represents a step in an API operation workflow. + * Represents a step in a REST operation workflow. * A step contains a call specification that defines which operation to invoke * and what parameters to pass to it. */ -public class ApiServerStepSpec { +public class RestServerStepSpec { @JsonInclude(JsonInclude.Include.NON_NULL) private volatile ServerCallSpec call; @@ -35,19 +36,19 @@ public class ApiServerStepSpec { @JsonInclude(JsonInclude.Include.NON_NULL) private volatile String description; - public ApiServerStepSpec() { + public RestServerStepSpec() { this(null, null, null); } - public ApiServerStepSpec(ServerCallSpec call) { + public RestServerStepSpec(ServerCallSpec call) { this(call, null, null); } - public ApiServerStepSpec(ServerCallSpec call, Map with) { + public RestServerStepSpec(ServerCallSpec call, Map with) { this(call, with, null); } - public ApiServerStepSpec(ServerCallSpec call, Map with, String description) { + public RestServerStepSpec(ServerCallSpec call, Map with, String description) { this.call = call; this.with = with != null ? new ConcurrentHashMap<>(with) : null; this.description = description; diff --git a/src/main/java/io/naftiko/spec/exposes/ExposedSkillSpec.java b/src/main/java/io/naftiko/spec/exposes/skill/ExposedSkillSpec.java similarity index 99% rename from src/main/java/io/naftiko/spec/exposes/ExposedSkillSpec.java rename to src/main/java/io/naftiko/spec/exposes/skill/ExposedSkillSpec.java index 989ca75..59c165d 100644 --- a/src/main/java/io/naftiko/spec/exposes/ExposedSkillSpec.java +++ b/src/main/java/io/naftiko/spec/exposes/skill/ExposedSkillSpec.java @@ -11,7 +11,7 @@ * or implied. See the License for the specific language governing permissions and limitations under * the License. */ -package io.naftiko.spec.exposes; +package io.naftiko.spec.exposes.skill; import java.util.List; import java.util.Map; diff --git a/src/main/java/io/naftiko/spec/exposes/SkillServerSpec.java b/src/main/java/io/naftiko/spec/exposes/skill/SkillServerSpec.java similarity index 96% rename from src/main/java/io/naftiko/spec/exposes/SkillServerSpec.java rename to src/main/java/io/naftiko/spec/exposes/skill/SkillServerSpec.java index 5cce5f2..11293ce 100644 --- a/src/main/java/io/naftiko/spec/exposes/SkillServerSpec.java +++ b/src/main/java/io/naftiko/spec/exposes/skill/SkillServerSpec.java @@ -11,11 +11,12 @@ * or implied. See the License for the specific language governing permissions and limitations under * the License. */ -package io.naftiko.spec.exposes; +package io.naftiko.spec.exposes.skill; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; import com.fasterxml.jackson.annotation.JsonInclude; +import io.naftiko.spec.exposes.ServerSpec; /** * Skill Server Specification Element. diff --git a/src/main/java/io/naftiko/spec/exposes/SkillToolFromSpec.java b/src/main/java/io/naftiko/spec/exposes/skill/SkillToolFromSpec.java similarity index 97% rename from src/main/java/io/naftiko/spec/exposes/SkillToolFromSpec.java rename to src/main/java/io/naftiko/spec/exposes/skill/SkillToolFromSpec.java index c5d704e..eb93b54 100644 --- a/src/main/java/io/naftiko/spec/exposes/SkillToolFromSpec.java +++ b/src/main/java/io/naftiko/spec/exposes/skill/SkillToolFromSpec.java @@ -11,7 +11,7 @@ * or implied. See the License for the specific language governing permissions and limitations under * the License. */ -package io.naftiko.spec.exposes; +package io.naftiko.spec.exposes.skill; /** * Source reference for a derived skill tool. diff --git a/src/main/java/io/naftiko/spec/exposes/SkillToolSpec.java b/src/main/java/io/naftiko/spec/exposes/skill/SkillToolSpec.java similarity index 97% rename from src/main/java/io/naftiko/spec/exposes/SkillToolSpec.java rename to src/main/java/io/naftiko/spec/exposes/skill/SkillToolSpec.java index 68cbb10..64041e5 100644 --- a/src/main/java/io/naftiko/spec/exposes/SkillToolSpec.java +++ b/src/main/java/io/naftiko/spec/exposes/skill/SkillToolSpec.java @@ -11,7 +11,7 @@ * or implied. See the License for the specific language governing permissions and limitations under * the License. */ -package io.naftiko.spec.exposes; +package io.naftiko.spec.exposes.skill; import com.fasterxml.jackson.annotation.JsonInclude; diff --git a/src/main/resources/blueprints/agent-skills-support-proposal.md b/src/main/resources/blueprints/agent-skills-support-proposal.md index 82873f2..ec7c98c 100644 --- a/src/main/resources/blueprints/agent-skills-support-proposal.md +++ b/src/main/resources/blueprints/agent-skills-support-proposal.md @@ -3,7 +3,7 @@ **Status**: Revised Proposal **Date**: March 5, 2026 -**Key Concept**: Dedicated `skill` server adapter — skills declare tools derived from sibling `api` and `mcp` adapters or defined as local file instructions. AI clients invoke adjacent adapters directly for derived tools. +**Key Concept**: Dedicated `skill` server adapter — skills declare tools derived from sibling `rest` and `mcp` adapters or defined as local file instructions. AI clients invoke adjacent adapters directly for derived tools. --- @@ -28,10 +28,10 @@ ### What This Proposes -Introduce a **dedicated `skill` server adapter** (alongside existing `api` and `mcp` adapters) enabling Naftiko capabilities to **describe skills and declare supporting tools**: +Introduce a **dedicated `skill` server adapter** (alongside existing `rest` and `mcp` adapters) enabling Naftiko capabilities to **describe skills and declare supporting tools**: 1. **Describe** skills with full [Agent Skills Spec](https://agentskills.io/specification) frontmatter metadata -2. **Declare tools** — each tool is either derived from a sibling `api`/`mcp` adapter operation, or defined as a local file instruction +2. **Declare tools** — each tool is either derived from a sibling `rest`/`mcp` adapter operation, or defined as a local file instruction 3. **Distribute** skills through predefined GET endpoints for discovery, download, and file browsing 4. **Locate** supporting files (SKILL.md, README, schemas) via a `location` property @@ -39,18 +39,18 @@ Skills can be **purely descriptive** (metadata + supporting files only), declare ### Why a Dedicated Adapter? -Just as the `mcp` adapter provides protocol-specific features despite HTTP being technically possible within `api`, the `skill` adapter provides: +Just as the `mcp` adapter provides protocol-specific features despite HTTP being technically possible within `rest`, the `skill` adapter provides: - **Catalog Model**: Describe skills that declare tools from sibling adapters or local instructions, giving agents a unified discovery surface - **Agent Skills Spec Alignment**: Full frontmatter support (name, description, license, compatibility, allowed-tools, argument-hint, invocation controls) - **Supporting Files**: `location` property links to SKILL.md and supporting documentation accessible via REST endpoints -- **Focused Responsibility**: Skill metadata concerns separate from tool execution (which stays with `api` and `mcp` adapters) +- **Focused Responsibility**: Skill metadata concerns separate from tool execution (which stays with `rest` and `mcp` adapters) ### Business Value | Benefit | Impact | Users | |---------|--------|-------| -| **Skill Cataloging** | Describe and organize tools from sibling API/MCP adapters and local instructions into discoverable skills | Developers | +| **Skill Cataloging** | Describe and organize tools from sibling REST/MCP adapters and local instructions into discoverable skills | Developers | | **Agent Discovery** | Agents discover skill tools with rich metadata, then invoke sibling adapters directly or read instruction files | AI Agents | | **No Duplication** | Derive tools from existing adapters without redefining tool logic | Architects | | **Distribution** | Predefined REST endpoints for discovery, download, and file browsing | Organizations | @@ -58,7 +58,7 @@ Just as the `mcp` adapter provides protocol-specific features despite HTTP being ### Key Design Decisions -1. **Metadata-First**: Skills describe and declare tools — they do not execute them. Tool execution stays with the `api` and `mcp` adapters that own the tools. +1. **Metadata-First**: Skills describe and declare tools — they do not execute them. Tool execution stays with the `rest` and `mcp` adapters that own the tools. 2. **Per-Tool Declaration**: Each skill declares its tools individually via `tools[]`. Each tool specifies its source: `from` (derived from a sibling adapter) or `instruction` (a local file). @@ -72,7 +72,7 @@ Just as the `mcp` adapter provides protocol-specific features despite HTTP being 7. **`location` for Supporting Files**: A `file:///` URI pointing to a directory containing SKILL.md and supporting files/folders, served through the `/contents` and `/download` endpoints. -8. **No Recursive Derivation**: Only sibling `api` or `mcp` adapters can be `from` sources — no derivation from other skill adapters. +8. **No Recursive Derivation**: Only sibling `rest` or `mcp` adapters can be `from` sources — no derivation from other skill adapters. ### Risk Assessment @@ -93,7 +93,7 @@ Just as the `mcp` adapter provides protocol-specific features despite HTTP being | Adapter | Purpose | Responsibility | |---------|---------|-----------------| -| **`api`** | REST API Server | HTTP endpoints, resource operations, tool execution via REST | +| **`rest`** | REST API Server | HTTP endpoints, resource operations, tool execution via REST | | **`mcp`** | MCP Protocol Server | MCP tools, stdio/HTTP transport, tool execution via MCP protocol | | **`skill`** (NEW) | Skill Catalog & Distribution | Agent skill metadata, tools (derived + instruction), supporting files | @@ -104,7 +104,7 @@ Each server adapter has: ### Proposed Architecture -The `skill` adapter is a **metadata and catalog layer** — it describes skills that declare tools from sibling `api` and `mcp` adapters or from local file instructions: +The `skill` adapter is a **metadata and catalog layer** — it describes skills that declare tools from sibling `rest` and `mcp` adapters or from local file instructions: ```yaml capability: @@ -152,8 +152,8 @@ capability: value: "$.lon" exposes: - # API adapter — owns tool execution via REST - - type: "api" + # REST adapter — owns tool execution via REST + - type: "rest" address: "0.0.0.0" port: 9090 namespace: "weather-rest" @@ -231,7 +231,7 @@ capability: - name: "get-forecast" description: "Get weather forecast for a city" from: - sourceNamespace: "weather-rest" # Sibling API adapter + sourceNamespace: "weather-rest" # Sibling REST adapter action: "get-forecast" # Operation name - name: "resolve-and-forecast" description: "Resolve a place name to coordinates, then fetch forecast" @@ -245,7 +245,7 @@ capability: **How agents use this:** 1. Agent calls `GET /skills/weather-forecast` → receives tool catalog -2. Agent sees `get-forecast` (derived) with `invocationRef: { targetNamespace: "weather-rest", mode: "api" }` → invokes `GET http://host:9090/forecast/London` +2. Agent sees `get-forecast` (derived) with `invocationRef: { targetNamespace: "weather-rest", mode: "rest" }` → invokes `GET http://host:9090/forecast/London` 3. Agent sees `resolve-and-forecast` (derived) with `invocationRef: { targetNamespace: "weather-mcp", mode: "mcp" }` → invokes via MCP protocol on port 9091 4. Agent sees `interpret-weather` (instruction) → reads instruction content via `GET /skills/weather-forecast/contents/interpret-weather.md` @@ -254,7 +254,7 @@ capability: ## Design Analogy ``` -API Adapter MCP Adapter SKILL Adapter +REST Adapter MCP Adapter SKILL Adapter ───────────── ───────────── ────────────── ExposesApi ExposesMcp ExposesSkill ├─ resources[] ├─ tools[] ├─ skills[] @@ -271,7 +271,7 @@ ExposesApi ExposesMcp ExposesSkill | Adapter | First-class construct | Actionable units | Execution | |---------|----------------------|-----------------|-----------| -| **`api`** | Resources | Operations | HTTP endpoints (call/steps/with) | +| **`rest`** | Resources | Operations | HTTP endpoints (call/steps/with) | | **`mcp`** | (flat) | Tools | MCP protocol (call/steps/with) | | **`skill`** | Skills | Tools (derived + instruction) | **None** — agents invoke sibling adapters or read instruction files | @@ -279,7 +279,7 @@ ExposesApi ExposesMcp ExposesSkill ## Skill Definition -Skills provide rich metadata and a unified discovery surface. Each skill can declare one or more **tools**, where each tool is either **derived** from a sibling `api` or `mcp` adapter, or defined as a local **instruction** file. Skills can also stand alone as purely descriptive (no tools). +Skills provide rich metadata and a unified discovery surface. Each skill can declare one or more **tools**, where each tool is either **derived** from a sibling `rest` or `mcp` adapter, or defined as a local **instruction** file. Skills can also stand alone as purely descriptive (no tools). ### Declaring Tools @@ -297,7 +297,7 @@ skills: location: "file:///etc/naftiko/skills/order-management" tools: - # Derived from sibling API adapter + # Derived from sibling REST adapter - name: "list-orders" description: "List all customer orders" from: @@ -325,7 +325,7 @@ skills: A tool with `from` references a specific operation or tool in a sibling adapter: **Tool declaration rules:** -1. `from.sourceNamespace` must resolve to a sibling `exposes[]` entry of type `api` or `mcp` +1. `from.sourceNamespace` must resolve to a sibling `exposes[]` entry of type `rest` or `mcp` 2. `from.action` must match an operation name (api) or tool name (mcp) in the resolved adapter 3. Adapter type is inferred from the resolved target 4. Each derived tool includes an `invocationRef` in the response so agents can invoke the source adapter directly @@ -339,7 +339,7 @@ A tool with `from` references a specific operation or tool in a sibling adapter: "invocationRef": { "targetNamespace": "public-api", "action": "list-orders", - "mode": "api" + "mode": "rest" }, "inputSchema": { "type": "object", @@ -533,7 +533,7 @@ The SKILL.md file at the location can contain the same frontmatter properties as ```json { "type": "object", - "description": "A skill definition. Declares tools derived from sibling api or mcp adapters or defined as local file instructions. Can also stand alone as purely descriptive (no tools). Supports full Agent Skills Spec frontmatter metadata. Skills describe tools — they do not execute them.", + "description": "A skill definition. Declares tools derived from sibling rest or mcp adapters or defined as local file instructions. Can also stand alone as purely descriptive (no tools). Supports full Agent Skills Spec frontmatter metadata. Skills describe tools — they do not execute them.", "properties": { "name": { "$ref": "#/$defs/IdentifierKebab", @@ -600,7 +600,7 @@ The SKILL.md file at the location can contain the same frontmatter properties as ```json { "type": "object", - "description": "A tool declared within a skill. Derived from a sibling api or mcp adapter via 'from', or defined as a local file instruction.", + "description": "A tool declared within a skill. Derived from a sibling rest or mcp adapter via 'from', or defined as a local file instruction.", "properties": { "name": { "$ref": "#/$defs/IdentifierKebab", @@ -612,11 +612,11 @@ The SKILL.md file at the location can contain the same frontmatter properties as }, "from": { "type": "object", - "description": "Derive this tool from a sibling api or mcp adapter.", + "description": "Derive this tool from a sibling rest or mcp adapter.", "properties": { "sourceNamespace": { "type": "string", - "description": "Sibling exposes[].namespace (must be type api or mcp)" + "description": "Sibling exposes[].namespace (must be type rest or mcp)" }, "action": { "type": "string", @@ -702,7 +702,7 @@ Response: application/json "invocationRef": { "targetNamespace": "weather-rest", "action": "get-forecast", - "mode": "api" + "mode": "rest" }, "inputSchema": { "type": "object", @@ -784,7 +784,7 @@ If no `location` is configured, the download and contents endpoints return 404. | EXPOSES | | +---------------------------+ +---------------------------+ | | | ExposesApi | | ExposesMcp | | -| | type: "api" | | type: "mcp" | | +| | type: "rest" | | type: "mcp" | | | | port: 9090 | | port: 9091 | | | | namespace: "weather-rest" | | namespace: "weather-mcp" | | | | resources / operations | | tools (call/steps/with) | | @@ -812,7 +812,7 @@ If no `location` is configured, the download and contents endpoints return 404. ``` +---------------------------+ +---------------------------+ +---------------------------+ -| API Adapter | | MCP Adapter | | SKILL Adapter | +| REST Adapter | | MCP Adapter | | SKILL Adapter | | (EXECUTES) | | (EXECUTES) | | (DESCRIBES) | +---------------------------+ +---------------------------+ +---------------------------+ | ExposesApi | | ExposesMcp | | ExposesSkill | @@ -868,7 +868,7 @@ AI Agent / Client | | args: { place: "London" } v v +---------------------+ +---------------------+ -| API Adapter (9090) | | MCP Adapter (9091) | +| REST Adapter (9090) | | MCP Adapter (9091) | | Executes via | | Executes via | | call/steps/with | | call/steps/with | +---------------------+ +---------------------+ @@ -1023,8 +1023,8 @@ capability: value: "$.lon" exposes: - # API adapter — executes the forecast tool via REST - - type: "api" + # REST adapter — executes the forecast tool via REST + - type: "rest" address: "0.0.0.0" port: 9090 namespace: "weather-rest" @@ -1130,7 +1130,7 @@ curl http://localhost:8080/skills/weather-forecast/contents | jq '.' curl http://localhost:8080/skills/weather-forecast/contents/interpret-weather.md # Agent invokes derived tools DIRECTLY through source adapter: -# Via REST API adapter: +# Via REST REST adapter: curl http://localhost:9090/forecast/London | jq '.' # Via MCP adapter (using MCP protocol, not curl): @@ -1174,7 +1174,7 @@ curl http://localhost:9090/forecast/London | jq '.' "invocationRef": { "targetNamespace": "weather-rest", "action": "get-forecast", - "mode": "api" + "mode": "rest" }, "inputSchema": { "type": "object", @@ -1213,7 +1213,7 @@ curl http://localhost:9090/forecast/London | jq '.' --- -### Example 2: Order Management — Tools from API Adapter +### Example 2: Order Management — Tools from REST Adapter **Scenario**: Catalog existing API operations as discoverable skill tools. @@ -1222,7 +1222,7 @@ naftiko: "0.5" info: label: "Order Management Platform" - description: "Skills derived from existing API adapters" + description: "Skills derived from existing REST adapters" capability: consumes: @@ -1258,8 +1258,8 @@ capability: name: "cancel-order" exposes: - # Sibling API adapter — executes tools - - type: "api" + # Sibling REST adapter — executes tools + - type: "rest" address: "0.0.0.0" port: 9090 namespace: "public-api" @@ -1281,7 +1281,7 @@ capability: name: "cancel-order" call: "orders-backend.cancel-order" - # Skill adapter — catalogs tools from API adapter + # Skill adapter — catalogs tools from REST adapter - type: "skill" address: "0.0.0.0" port: 8080 @@ -1335,7 +1335,7 @@ capability: "invocationRef": { "targetNamespace": "public-api", "action": "list-orders", - "mode": "api" + "mode": "rest" } }, { @@ -1345,7 +1345,7 @@ capability: "invocationRef": { "targetNamespace": "public-api", "action": "get-order", - "mode": "api" + "mode": "rest" } }, { @@ -1355,7 +1355,7 @@ capability: "invocationRef": { "targetNamespace": "public-api", "action": "create-order", - "mode": "api" + "mode": "rest" } } ] @@ -1392,8 +1392,8 @@ capability: value: "$.result" exposes: - # REST API adapter - - type: "api" + # REST REST adapter + - type: "rest" address: "0.0.0.0" port: 9090 namespace: "analytics-rest" @@ -1591,7 +1591,7 @@ spec: 1. `tools` is optional — a skill can be purely descriptive (metadata + `location` only, no tools) 2. Each tool must specify exactly one source: `from` (derived) or `instruction` (local file) -3. For derived tools (`from`), `sourceNamespace` must resolve to exactly one sibling `exposes[].namespace` of type `api` or `mcp` +3. For derived tools (`from`), `sourceNamespace` must resolve to exactly one sibling `exposes[].namespace` of type `rest` or `mcp` 4. Referencing a `skill`-type adapter from `from.sourceNamespace` is invalid (no recursive derivation) 5. For derived tools, `action` must exist as an operation name (api) or tool name (mcp) in the resolved adapter 6. For instruction tools, the skill must have a `location` configured — the instruction path is resolved relative to it @@ -1621,7 +1621,7 @@ spec: ## Why This Architecture Works -1. **Clear Separation of Concerns**: Skills describe; `api` and `mcp` adapters execute. Each adapter does one thing well. +1. **Clear Separation of Concerns**: Skills describe; `rest` and `mcp` adapters execute. Each adapter does one thing well. 2. **No Duplication**: Derived tools reference operations already defined in adjacent adapters — no need to redefine tool logic. Instruction tools add knowledge without duplicating execution. @@ -1631,6 +1631,6 @@ spec: 5. **Direct Invocation**: Agents discover tools through the skill catalog, then invoke the source adapter directly — no proxy overhead, no execution complexity in the skill layer. -6. **Composable**: A skill can declare derived tools from multiple sibling adapters (both `api` and `mcp`) and instruction tools from local files, providing a unified discovery surface. +6. **Composable**: A skill can declare derived tools from multiple sibling adapters (both `rest` and `mcp`) and instruction tools from local files, providing a unified discovery surface. 7. **Enterprise Ready**: Auth, metadata governance, and file distribution endpoints support internal hosting and access control. diff --git a/src/main/resources/blueprints/gap-analysis-report.md b/src/main/resources/blueprints/gap-analysis-report.md index d5ea806..ac4ae1d 100644 --- a/src/main/resources/blueprints/gap-analysis-report.md +++ b/src/main/resources/blueprints/gap-analysis-report.md @@ -21,7 +21,7 @@ The Naftiko framework has **strong implementation coverage** of core specificati ## 1. EXPOSITION TYPES -### 1.1 REST API Exposition (`type: api`) +### 1.1 REST API Exposition (`type: rest`) **Spec Definition** (v0.5): - Address and port binding @@ -499,7 +499,7 @@ Input parameters available in path, query, header, cookie, body, environment loc **Implementation Status**: ✅ **FULLY IMPLEMENTED** -**For Exposed API/MCP**: +**For Exposed REST/MCP**: ```java // From ExposedInputParameter spec - name: user_id diff --git a/src/main/resources/blueprints/kubernetes-backstage-governance-proposal.md b/src/main/resources/blueprints/kubernetes-backstage-governance-proposal.md index 9e1665b..345bf13 100644 --- a/src/main/resources/blueprints/kubernetes-backstage-governance-proposal.md +++ b/src/main/resources/blueprints/kubernetes-backstage-governance-proposal.md @@ -150,7 +150,7 @@ The exposed adapter is a published API contract. Two new fields signal network t ```yaml exposes: - - type: api + - type: rest port: 3000 namespace: notion-writer lifecycle: production @@ -258,7 +258,7 @@ Naftiko Spec Object tags labels lifecycle ────────────────────────────────────────────────────────────── Info ✓ (existing) ✓ (new) Consumes ✓ (new) -Exposes (API adapter) ✓ (new) ✓ (new) +Exposes (REST adapter) ✓ (new) ✓ (new) ExposedOperation ✓ (new) ConsumedHttpOperation ✓ (new) ``` @@ -294,7 +294,7 @@ spec: email: jane.doe@example.com capability: exposes: - - type: api + - type: rest port: 3000 namespace: notion-writer lifecycle: production @@ -466,7 +466,7 @@ Both are implemented in the shared `@naftiko/rules` TypeScript package (see [Sec ### 5.2 Core Rules (Error Severity — Blocking) #### `naftiko-exposes-require-authentication` -Every exposed API adapter must declare `authentication`. All exposed APIs must be authenticated. +Every exposed REST adapter must declare `authentication`. All exposed APIs must be authenticated. - **Given**: `$.capability.exposes[*]` - **Check**: `authentication` field is present and truthy diff --git a/src/main/resources/blueprints/mcp-resources-prompts-proposal.md b/src/main/resources/blueprints/mcp-resources-prompts-proposal.md index 47a6cdb..88f95a2 100644 --- a/src/main/resources/blueprints/mcp-resources-prompts-proposal.md +++ b/src/main/resources/blueprints/mcp-resources-prompts-proposal.md @@ -3,7 +3,7 @@ **Status**: Proposal **Date**: March 5, 2026 -**Key Concept**: Add MCP resources and prompt templates to the existing `mcp` server adapter, aligning with the MCP specification while maintaining consistency with the existing `api` adapter patterns and the Agent Skills proposal's `location`-based file serving. +**Key Concept**: Add MCP resources and prompt templates to the existing `mcp` server adapter, aligning with the MCP specification while maintaining consistency with the existing `rest` adapter patterns and the Agent Skills proposal's `location`-based file serving. --- @@ -134,7 +134,7 @@ ExposesMcp ### How the three primitives relate across adapters ``` -API Adapter MCP Adapter (current) MCP Adapter (proposed) +REST Adapter MCP Adapter (current) MCP Adapter (proposed) ───────────── ───────────────────── ────────────────────── ExposesApi ExposesMcp ExposesMcp ├─ resources[] ├─ tools[] ├─ tools[] @@ -159,9 +159,9 @@ ExposesApi ExposesMcp ExposesMcp │ │ └─ template / location ``` -### Conceptual mapping: API adapter ↔ MCP adapter +### Conceptual mapping: REST adapter ↔ MCP adapter -| API Adapter concept | MCP Tool (existing) | MCP Resource (new) | MCP Prompt (new) | +| REST Adapter concept | MCP Tool (existing) | MCP Resource (new) | MCP Prompt (new) | |---------------------|--------------------:|-------------------:|------------------:| | Resource path | Tool name | Resource URI | Prompt name | | Operation (GET/POST) | `call`/`steps` | `call`/`steps` or `location` | `template`/`location` | diff --git a/src/main/resources/schemas/examples/cir.yml b/src/main/resources/schemas/examples/cir.yml index 37eb0c9..d86a1bd 100644 --- a/src/main/resources/schemas/examples/cir.yml +++ b/src/main/resources/schemas/examples/cir.yml @@ -30,7 +30,7 @@ externalRefs: capability: exposes: - - type: "api" + - type: "rest" address: "localhost" port: 8090 namespace: "cir" diff --git a/src/main/resources/schemas/examples/multi-consumes-rest-adapter.yml b/src/main/resources/schemas/examples/multi-consumes-rest-adapter.yml index 1c2bf71..06ce6ef 100644 --- a/src/main/resources/schemas/examples/multi-consumes-rest-adapter.yml +++ b/src/main/resources/schemas/examples/multi-consumes-rest-adapter.yml @@ -16,7 +16,7 @@ info: capability: exposes: - - type: "api" + - type: "rest" address: "localhost" port: 9090 namespace: "sample" diff --git a/src/main/resources/schemas/examples/multi-consumes-with-auth.yml b/src/main/resources/schemas/examples/multi-consumes-with-auth.yml index 9791eab..cd6cb6d 100644 --- a/src/main/resources/schemas/examples/multi-consumes-with-auth.yml +++ b/src/main/resources/schemas/examples/multi-consumes-with-auth.yml @@ -7,7 +7,7 @@ info: capability: exposes: - namespace: "local-api" - type: api + type: rest address: "localhost" port: 8080 resources: diff --git a/src/main/resources/schemas/examples/no-adapter.yml b/src/main/resources/schemas/examples/no-adapter.yml index ae084c5..24a9ac9 100644 --- a/src/main/resources/schemas/examples/no-adapter.yml +++ b/src/main/resources/schemas/examples/no-adapter.yml @@ -16,7 +16,7 @@ info: capability: exposes: - - type: "api" + - type: "rest" address: "localhost" port: 9090 namespace: "sample" diff --git a/src/main/resources/schemas/examples/notion-sandbox.yml b/src/main/resources/schemas/examples/notion-sandbox.yml index efbb2b3..91a740d 100644 --- a/src/main/resources/schemas/examples/notion-sandbox.yml +++ b/src/main/resources/schemas/examples/notion-sandbox.yml @@ -6,7 +6,7 @@ info: description: "This is a capability enabling consumption of Notion API." capability: exposes: - - type: "api" + - type: "rest" address: "localhost" namespace: "notion-api-proxy" port: 8080 diff --git a/src/main/resources/schemas/examples/notion.yml b/src/main/resources/schemas/examples/notion.yml index 0dfbeff..318e1c2 100644 --- a/src/main/resources/schemas/examples/notion.yml +++ b/src/main/resources/schemas/examples/notion.yml @@ -27,7 +27,7 @@ externalRefs: capability: exposes: - - type: "api" + - type: "rest" address: "localhost" port: 9090 namespace: "sample" diff --git a/src/main/resources/schemas/examples/skill-adapter.yml b/src/main/resources/schemas/examples/skill-adapter.yml index 11f02fb..36c93d2 100644 --- a/src/main/resources/schemas/examples/skill-adapter.yml +++ b/src/main/resources/schemas/examples/skill-adapter.yml @@ -7,7 +7,7 @@ info: capability: exposes: - - type: api + - type: rest port: 3000 namespace: weather-api resources: diff --git a/src/main/resources/schemas/naftiko-schema.json b/src/main/resources/schemas/naftiko-schema.json index 13f0517..71004f8 100644 --- a/src/main/resources/schemas/naftiko-schema.json +++ b/src/main/resources/schemas/naftiko-schema.json @@ -667,7 +667,7 @@ "items": { "oneOf": [ { - "$ref": "#/$defs/ExposesApi" + "$ref": "#/$defs/ExposesRest" }, { "$ref": "#/$defs/ExposesMcp" @@ -708,13 +708,13 @@ ], "additionalProperties": false }, - "ExposesApi": { + "ExposesRest": { "type": "object", - "description": "API exposition configuration", + "description": "REST exposition configuration", "properties": { "type": { "type": "string", - "const": "api" + "const": "rest" }, "address": { "$ref": "#/$defs/Address" diff --git a/src/main/resources/schemas/tutorial/step-1-my-first-capability.yml b/src/main/resources/schemas/tutorial/step-1-my-first-capability.yml index 4015ecd..f37838c 100644 --- a/src/main/resources/schemas/tutorial/step-1-my-first-capability.yml +++ b/src/main/resources/schemas/tutorial/step-1-my-first-capability.yml @@ -1,7 +1,7 @@ naftiko: "0.5" capability: exposes: - - type: "api" + - type: "rest" port: 8081 namespace: "tutorial" resources: diff --git a/src/main/resources/schemas/tutorial/step-2-forwarding-api-resource.yml b/src/main/resources/schemas/tutorial/step-2-forwarding-api-resource.yml index 5d00665..3ed60b7 100644 --- a/src/main/resources/schemas/tutorial/step-2-forwarding-api-resource.yml +++ b/src/main/resources/schemas/tutorial/step-2-forwarding-api-resource.yml @@ -1,7 +1,7 @@ naftiko: "0.5" capability: exposes: - - type: "api" + - type: "rest" port: 8081 namespace: "sample" resources: diff --git a/src/main/resources/schemas/tutorial/step-3-encapsulating-headers.yml b/src/main/resources/schemas/tutorial/step-3-encapsulating-headers.yml index 75683b1..61fd96b 100644 --- a/src/main/resources/schemas/tutorial/step-3-encapsulating-headers.yml +++ b/src/main/resources/schemas/tutorial/step-3-encapsulating-headers.yml @@ -1,7 +1,7 @@ naftiko: "0.5" capability: exposes: - - type: "api" + - type: "rest" port: 8081 namespace: "sample" resources: diff --git a/src/main/resources/schemas/tutorial/step-4-filter-reponse.yml b/src/main/resources/schemas/tutorial/step-4-filter-reponse.yml index d79eed8..1d672ff 100644 --- a/src/main/resources/schemas/tutorial/step-4-filter-reponse.yml +++ b/src/main/resources/schemas/tutorial/step-4-filter-reponse.yml @@ -1,7 +1,7 @@ naftiko: "0.5" capability: exposes: - - type: "api" + - type: "rest" port: 8081 namespace: "sample" resources: diff --git a/src/main/resources/schemas/tutorial/step-5-multi-steps.yml b/src/main/resources/schemas/tutorial/step-5-multi-steps.yml index 05606af..0bf9058 100644 --- a/src/main/resources/schemas/tutorial/step-5-multi-steps.yml +++ b/src/main/resources/schemas/tutorial/step-5-multi-steps.yml @@ -14,7 +14,7 @@ info: capability: exposes: - - type: "api" + - type: "rest" port: 8081 namespace: "my-capability" resources: diff --git a/src/main/resources/schemas/tutorial/step1-hello-world.yml b/src/main/resources/schemas/tutorial/step1-hello-world.yml index 5a1a9fa..c1d1046 100644 --- a/src/main/resources/schemas/tutorial/step1-hello-world.yml +++ b/src/main/resources/schemas/tutorial/step1-hello-world.yml @@ -1,4 +1,4 @@ -# yaml-language-server: $schema=../capability-schema.json +# yaml-language-server: $schema=../naftiko-schema.json --- naftiko: "0.5" info: @@ -16,7 +16,7 @@ info: capability: exposes: - - type: "api" + - type: "rest" address: "localhost" port: 9090 namespace: "tutorial" diff --git a/src/main/resources/schemas/tutorial/step2-forward.yml b/src/main/resources/schemas/tutorial/step2-forward.yml index 00a1780..d4b3a12 100644 --- a/src/main/resources/schemas/tutorial/step2-forward.yml +++ b/src/main/resources/schemas/tutorial/step2-forward.yml @@ -1,4 +1,4 @@ -# yaml-language-server: $schema=../capability-schema.json +# yaml-language-server: $schema=../naftiko-schema.json --- naftiko: "0.5" info: @@ -16,7 +16,7 @@ info: capability: exposes: - - type: "api" + - type: "rest" address: "localhost" port: 9090 namespace: "sample" diff --git a/src/main/resources/schemas/tutorial/step3a-encapsulate.yml b/src/main/resources/schemas/tutorial/step3a-encapsulate.yml index 2f91259..16234b6 100644 --- a/src/main/resources/schemas/tutorial/step3a-encapsulate.yml +++ b/src/main/resources/schemas/tutorial/step3a-encapsulate.yml @@ -1,4 +1,4 @@ -# yaml-language-server: $schema=../capability-schema.json +# yaml-language-server: $schema=../naftiko-schema.json --- naftiko: "0.5" info: @@ -16,7 +16,7 @@ info: capability: exposes: - - type: "api" + - type: "rest" address: "localhost" port: 9090 namespace: "sample" diff --git a/src/main/resources/schemas/tutorial/step3b-encapsulate.yml b/src/main/resources/schemas/tutorial/step3b-encapsulate.yml index c732dcb..95bb1cd 100644 --- a/src/main/resources/schemas/tutorial/step3b-encapsulate.yml +++ b/src/main/resources/schemas/tutorial/step3b-encapsulate.yml @@ -1,4 +1,4 @@ -# yaml-language-server: $schema=../capability-schema.json +# yaml-language-server: $schema=../naftiko-schema.json --- naftiko: "0.5" info: @@ -16,7 +16,7 @@ info: capability: exposes: - - type: "api" + - type: "rest" address: "localhost" port: 9090 namespace: "sample" diff --git a/src/main/resources/schemas/tutorial/step3c-encapsulate.yml b/src/main/resources/schemas/tutorial/step3c-encapsulate.yml index 8214a3a..c1bdde9 100644 --- a/src/main/resources/schemas/tutorial/step3c-encapsulate.yml +++ b/src/main/resources/schemas/tutorial/step3c-encapsulate.yml @@ -1,4 +1,4 @@ -# yaml-language-server: $schema=../capability-schema.json +# yaml-language-server: $schema=../naftiko-schema.json --- naftiko: "0.5" info: @@ -16,7 +16,7 @@ info: capability: exposes: - - type: "api" + - type: "rest" address: "localhost" port: 9090 namespace: "sample" diff --git a/src/main/resources/schemas/tutorial/step4a-structure.yml b/src/main/resources/schemas/tutorial/step4a-structure.yml index ea740a1..59f8a42 100644 --- a/src/main/resources/schemas/tutorial/step4a-structure.yml +++ b/src/main/resources/schemas/tutorial/step4a-structure.yml @@ -1,4 +1,4 @@ -# yaml-language-server: $schema=../capability-schema.json +# yaml-language-server: $schema=../naftiko-schema.json --- naftiko: "0.5" info: @@ -16,7 +16,7 @@ info: capability: exposes: - - type: "api" + - type: "rest" address: "localhost" port: 9090 namespace: "sample" diff --git a/src/main/resources/schemas/tutorial/step4b-structure.yml b/src/main/resources/schemas/tutorial/step4b-structure.yml index 19cf624..10e78eb 100644 --- a/src/main/resources/schemas/tutorial/step4b-structure.yml +++ b/src/main/resources/schemas/tutorial/step4b-structure.yml @@ -1,4 +1,4 @@ -# yaml-language-server: $schema=../capability-schema.json +# yaml-language-server: $schema=../naftiko-schema.json --- naftiko: "0.5" @@ -27,7 +27,7 @@ externalRefs: capability: exposes: - - type: "api" + - type: "rest" address: "localhost" port: 9090 namespace: "sample" diff --git a/src/main/resources/schemas/tutorial/step5a-auth-bearer.yml b/src/main/resources/schemas/tutorial/step5a-auth-bearer.yml index bb84130..8d38bbb 100644 --- a/src/main/resources/schemas/tutorial/step5a-auth-bearer.yml +++ b/src/main/resources/schemas/tutorial/step5a-auth-bearer.yml @@ -1,4 +1,4 @@ -# yaml-language-server: $schema=../capability-schema.json +# yaml-language-server: $schema=../naftiko-schema.json --- naftiko: "0.5" info: @@ -25,7 +25,7 @@ externalRefs: capability: exposes: - - type: "api" + - type: "rest" address: "localhost" port: 9090 namespace: "tutorial" diff --git a/src/main/resources/schemas/tutorial/step5b-auth-apikey.yml b/src/main/resources/schemas/tutorial/step5b-auth-apikey.yml index e9ae285..b10a61f 100644 --- a/src/main/resources/schemas/tutorial/step5b-auth-apikey.yml +++ b/src/main/resources/schemas/tutorial/step5b-auth-apikey.yml @@ -1,4 +1,4 @@ -# yaml-language-server: $schema=../capability-schema.json +# yaml-language-server: $schema=../naftiko-schema.json --- naftiko: "0.5" info: @@ -25,7 +25,7 @@ externalRefs: capability: exposes: - - type: "api" + - type: "rest" address: "localhost" port: 9090 namespace: "tutorial" diff --git a/src/main/resources/wiki/FAQ.md b/src/main/resources/wiki/FAQ.md index 0d5d82a..9f0a83d 100644 --- a/src/main/resources/wiki/FAQ.md +++ b/src/main/resources/wiki/FAQ.md @@ -74,15 +74,15 @@ Example: A capability that consumes the Notion API and GitHub API, then exposes ### Q: What's the difference between API and MCP exposure? **A:** -| Feature | API (REST) | MCP | +| Feature | REST | MCP | |---------|-----------|-----| | **Protocol** | HTTP/REST | Model Context Protocol (JSON-RPC) | | **Best for** | General-purpose integrations, web apps | AI agent-native integrations | | **Tool discovery** | Manual or via OpenAPI | Automatic via MCP protocol | -| **Configuration** | `type: "api"` with resources/operations | `type: "mcp"` with tools | +| **Configuration** | `type: "rest"` with resources/operations | `type: "mcp"` with tools | | **Default transport** | HTTP | stdio or HTTP (streamable) | -**Use API** for traditional REST clients, web applications, or when you want standard HTTP semantics. +**Use REST** for traditional REST clients, web applications, or when you want standard HTTP semantics. **Use MCP** when exposing capabilities to AI agents or Claude. ### Q: What is a "namespace"? @@ -290,7 +290,7 @@ docker run -e GITHUB_TOKEN=ghp_xxx -e NOTION_TOKEN=secret_xxx ... ```yaml exposes: - - type: api + - type: rest port: 8081 namespace: my-api authentication: @@ -399,7 +399,7 @@ This forwards `GET /github/repos/owner/name` to GitHub's `/repos/owner/name`. ## 📡 MCP-Specific ### Q: How do I expose a capability as an MCP tool? -**A:** Use `type: mcp` in exposes instead of `type: api`: +**A:** Use `type: mcp` in exposes instead of `type: rest`: ```yaml exposes: @@ -645,12 +645,12 @@ This way, Capability B can combine Capability A with other APIs. Check the [Roadmap](https://github.com/naftiko/framework/wiki/Roadmap) for planned features. -### Q: Can I expose the same capability on both API and MCP? +### Q: Can I expose the same capability on both REST and MCP? **A:** Yes! Add multiple entries to `exposes`: ```yaml exposes: - - type: api + - type: rest port: 8081 namespace: rest-api resources: [...] diff --git a/src/main/resources/wiki/Specification.md b/src/main/resources/wiki/Specification.md index 865a65b..c346885 100644 --- a/src/main/resources/wiki/Specification.md +++ b/src/main/resources/wiki/Specification.md @@ -51,7 +51,7 @@ The JSON Schema for the Naftiko Specification is available in two forms: **MCP Server**: An exposition adapter that exposes capability operations as MCP tools, enabling AI agent integration via Streamable HTTP or stdio transport. -**Skill Server**: An exposition adapter that exposes a read-only catalog of agent skills — metadata, tool references, and supporting files — over predefined HTTP endpoints. Skills describe how to invoke tools in sibling API or MCP adapters. +**Skill Server**: An exposition adapter that exposes a read-only catalog of agent skills — metadata, tool references, and supporting files — over predefined HTTP endpoints. Skills describe how to invoke tools in sibling REST or MCP adapters. **ExternalRef**: A declaration of an external reference providing variables to the capability. Two variants: file-resolved (for development) and runtime-resolved (for production). Variables are explicitly declared via a `keys` map. @@ -189,7 +189,7 @@ Defines the technical configuration of the capability. | Field Name | Type | Description | | --- | --- | --- | -| **exposes** | `Exposes[]` | List of exposed server adapters. Each entry is an API Expose (`type: "api"`), an MCP Expose (`type: "mcp"`), or a Skill Expose (`type: "skill"`). | +| **exposes** | `Exposes[]` | List of exposed server adapters. Each entry is a REST Expose (`type: "rest"`), an MCP Expose (`type: "mcp"`), or a Skill Expose (`type: "skill"`). | | **consumes** | `Consumes[]` | List of consumed client adapters. | #### 3.4.2 Rules @@ -214,7 +214,7 @@ When multiple `consumes` entries are present: ```yaml capability: exposes: - - type: api + - type: rest port: 3000 namespace: tasks-api resources: @@ -254,21 +254,21 @@ capability: Describes a server adapter that exposes functionality. -> Update (schema v0.5): Two exposition adapter types are now supported — **API** (`type: "api"`) and **MCP** (`type: "mcp"`). Legacy `httpProxy` / `rest` exposition types are not part of the JSON Schema anymore. +> Update (schema v0.5): Two exposition adapter types are now supported — **REST** (`type: "rest"`) and **MCP** (`type: "mcp"`). Legacy `httpProxy` exposition types are not part of the JSON Schema anymore. > -#### 3.5.1 API Expose +#### 3.5.1 REST Expose -API exposition configuration. +REST exposition configuration. -> Update (schema v0.5): The Exposes object is now a discriminated union (`oneOf`) between **API** (`type: "api"`, this section) and **MCP** (`type: "mcp"`, see §3.5.4). The `type` field acts as discriminator. +> Update (schema v0.5): The Exposes object is now a discriminated union (`oneOf`) between **REST** (`type: "rest"`, this section) and **MCP** (`type: "mcp"`, see §3.5.4). The `type` field acts as discriminator. > **Fixed Fields:** | Field Name | Type | Description | | --- | --- | --- | -| **type** | `string` | **REQUIRED**. MUST be `"api"`. | +| **type** | `string` | **REQUIRED**. MUST be `"rest"`. | | **address** | `string` | Server address. Can be a hostname, IPv4, or IPv6 address. | | **port** | `integer` | **REQUIRED**. Port number. MUST be between 1 and 65535. | | **authentication** | `Authentication` | Authentication configuration. | @@ -415,10 +415,10 @@ Declares an input parameter for an MCP tool. These become properties in the tool #### 3.5.8 Exposes Object Examples -**API Expose with operations:** +**REST Expose with operations:** ```yaml -type: api +type: rest port: 3000 namespace: sample resources: @@ -434,10 +434,10 @@ resources: mapping: $.status ``` -**API Expose with forward:** +**REST Expose with forward:** ```yaml -type: api +type: rest port: 8080 namespace: proxy resources: @@ -449,10 +449,10 @@ resources: - Notion-Version ``` -**API Expose with both operations and forward:** +**REST Expose with both operations and forward:** ```yaml -type: api +type: rest port: 9090 namespace: hybrid resources: @@ -521,7 +521,7 @@ Skill exposition configuration. Exposes a read-only catalog of agent skills with - The `namespace` field is mandatory and MUST be unique across all exposes entries. - The `skills` array MUST contain at least one entry. - Each skill's tools must include exactly one of `from` (derived from a sibling adapter) or `instruction` (path to a local file). -- `from` tool references MUST resolve to a sibling `api` or `mcp` adapter namespace. +- `from` tool references MUST resolve to a sibling `rest` or `mcp` adapter namespace. - `instruction` tools require the skill's `location` field to be set. - No additional properties are allowed. @@ -562,13 +562,13 @@ A tool declared within a skill. Exactly one of `from` or `instruction` MUST be s | Field Name | Type | Description | | --- | --- | --- | -| **namespace** | `string` | **REQUIRED**. Namespace of the sibling `api` or `mcp` adapter. | +| **namespace** | `string` | **REQUIRED**. Namespace of the sibling `rest` or `mcp` adapter. | | **action** | `string` | **REQUIRED**. Operation or tool name within the referenced namespace. | **Rules:** - Exactly one of `from` or `instruction` MUST be present — not both, not neither. -- `from.namespace` MUST reference a sibling `api` or `mcp` adapter. +- `from.namespace` MUST reference a sibling `rest` or `mcp` adapter. - `instruction` is a relative file path from the skill's `location` directory. #### 3.5.12 Skill Expose Example @@ -1390,7 +1390,7 @@ And the exposed side of the capability: ```yaml # In exposes exposes: - - type: "api" + - type: "rest" address: "localhost" port: 9090 namespace: "sample" @@ -1845,7 +1845,7 @@ info: capability: exposes: - - type: "api" + - type: "rest" port: 8080 namespace: "proxy" resources: @@ -1893,7 +1893,7 @@ info: capability: exposes: - - type: "api" + - type: "rest" port: 3000 namespace: "app" resources: @@ -1973,7 +1973,7 @@ info: capability: exposes: - - type: "api" + - type: "rest" port: 9090 namespace: "inspector" resources: @@ -2083,7 +2083,7 @@ info: capability: exposes: - - type: "api" + - type: "rest" port: 4000 namespace: "team" resources: @@ -2192,7 +2192,7 @@ info: capability: exposes: - - type: "api" + - type: "rest" port: 9090 namespace: "dashboard" resources: diff --git a/src/main/resources/wiki/Tutorial.md b/src/main/resources/wiki/Tutorial.md index c05e8cb..c089fad 100644 --- a/src/main/resources/wiki/Tutorial.md +++ b/src/main/resources/wiki/Tutorial.md @@ -5,12 +5,12 @@ Welcome to the tutorial for Naftiko Framework. Starting with the simplest "Hello Please read the [installation instructions](https://github.com/naftiko/framework/wiki/Installation) to know how to run the Naftiko Engine with your capability file. ## 1. My first capability -Start with a very basic capability returning "Hello, World!", using only an API server adapter with constants. +Start with a very basic capability returning "Hello, World!", using only a REST server adapter with constants. ``` naftiko: "0.4" capability: exposes: - - type: "api" + - type: "rest" port: 8081 namespace: "tutorial" resources: @@ -42,7 +42,7 @@ info: capability: exposes: - - type: "api" + - type: "rest" port: 8081 namespace: "sample" resources: @@ -93,7 +93,7 @@ info: capability: exposes: - - type: "api" + - type: "rest" port: 8081 namespace: "sample" resources: @@ -133,7 +133,7 @@ info: capability: exposes: - - type: "api" + - type: "rest" port: 8081 namespace: "sample" resources: @@ -202,7 +202,7 @@ info: capability: exposes: - - type: "api" + - type: "rest" port: 8081 namespace: "my-capability" resources: diff --git a/src/main/resources/wiki/Use-cases.md b/src/main/resources/wiki/Use-cases.md index ee26f7b..1cbb9a5 100644 --- a/src/main/resources/wiki/Use-cases.md +++ b/src/main/resources/wiki/Use-cases.md @@ -6,7 +6,7 @@ Connect AI assistants to your systems through capabilities, so they can access t How Naftiko achieves this technically: - Declare upstream systems in `capability.consumes` (typically `type: http`) with `namespace`, `baseUri`, authentication, headers, and operation contracts. -- Expose the same domain as `type: mcp` tools and/or `type: api` resources in `capability.exposes`, so both AI agents and traditional clients use one integration layer. +- Expose the same domain as `type: mcp` tools and/or `type: rest` resources in `capability.exposes`, so both AI agents and traditional clients use one integration layer. - Use `call`, `with`, `steps`, and JSONPath `mapping` in `outputParameters` to return normalized, task-ready payloads instead of raw provider responses. ![Integrate AI](https://naftiko.github.io/docs/images/technology/use_case_AI_integration.png) @@ -44,7 +44,7 @@ How Naftiko achieves this technically: - [x] Pass thru source capability - [x] One source HTTP adapter per capability - [x] Multiple source HTTP adapters per capability -- [x] Declarative source HTTP adapter and target API adapter +- [x] Declarative source HTTP adapter and target REST adapter - [x] Focus on source APIs with JSON payloads - [x] Change HTTP methods to expose proper semantics - E.g. Adapt read-only POST queries into cacheable GET queries @@ -78,7 +78,7 @@ How Naftiko achieves this technically: ![Rightsize microservices](https://naftiko.github.io/docs/images/technology/use_case_api_reusability_rightsize_microservices.png) #### Key features -- [x] Declarative source HTTP adapter and target API adapter +- [x] Declarative source HTTP adapter and target REST adapter - [x] Finish support for source APIs with JSON payloads - [x] Convert YAML, Protobuf, payloads to JSON - [x] Support sequence of steps with calls @@ -107,7 +107,7 @@ How Naftiko achieves this technically: #### Key features - [x] Declarative target API contract with mocking mode - - [x] Allow API server adapter with no source HTTP adapter + - [x] Allow REST server adapter with no source HTTP adapter - [x] Use static value of output parameters as sample ## 8. API-first design @@ -115,7 +115,7 @@ How Naftiko achieves this technically: Start from existing APIs and define reusable capabilities on top, so API investments can power new AI and app experiences. How Naftiko achieves this technically: -- Begin with consumed API declarations (`baseUri`, auth, resources, operations), then incrementally add exposed API/MCP adapters. +- Begin with consumed API declarations (`baseUri`, auth, resources, operations), then incrementally add exposed REST/MCP adapters. - Reuse existing security and configuration using `externalRefs` with file/runtime resolution and injected variables (e.g., `{{token}}`). - Add format-aware parsing and mapping (JSON, YAML, XML, CSV, Avro, Protobuf support in the framework) to normalize diverse backends. diff --git a/src/test/java/io/naftiko/engine/CapabilityAvroIntegrationTest.java b/src/test/java/io/naftiko/engine/CapabilityAvroIntegrationTest.java index cb2e127..b402d73 100644 --- a/src/test/java/io/naftiko/engine/CapabilityAvroIntegrationTest.java +++ b/src/test/java/io/naftiko/engine/CapabilityAvroIntegrationTest.java @@ -21,7 +21,7 @@ import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; import io.naftiko.Capability; import io.naftiko.spec.NaftikoSpec; -import io.naftiko.spec.consumes.HttpClientSpec; +import io.naftiko.spec.consumes.http.HttpClientSpec; import java.io.File; public class CapabilityAvroIntegrationTest { diff --git a/src/test/java/io/naftiko/engine/CapabilityForwardHeaderIntegrationTest.java b/src/test/java/io/naftiko/engine/CapabilityForwardHeaderIntegrationTest.java index 67e5cd1..012229b 100644 --- a/src/test/java/io/naftiko/engine/CapabilityForwardHeaderIntegrationTest.java +++ b/src/test/java/io/naftiko/engine/CapabilityForwardHeaderIntegrationTest.java @@ -31,11 +31,11 @@ import com.sun.net.httpserver.HttpHandler; import com.sun.net.httpserver.HttpServer; import io.naftiko.Capability; -import io.naftiko.engine.exposes.ApiResourceRestlet; -import io.naftiko.engine.exposes.ApiServerAdapter; +import io.naftiko.engine.exposes.rest.RestResourceRestlet; +import io.naftiko.engine.exposes.rest.RestServerAdapter; import io.naftiko.spec.NaftikoSpec; -import io.naftiko.spec.exposes.ApiServerResourceSpec; -import io.naftiko.spec.exposes.ApiServerSpec; +import io.naftiko.spec.exposes.rest.RestServerResourceSpec; +import io.naftiko.spec.exposes.rest.RestServerSpec; public class CapabilityForwardHeaderIntegrationTest { @@ -70,7 +70,7 @@ public void handle(HttpExchange exchange) { naftiko: \"0.4\" capability: exposes: - - type: \"api\" + - type: \"rest\" address: \"localhost\" port: 0 namespace: \"sample\" @@ -96,17 +96,17 @@ public void handle(HttpExchange exchange) { NaftikoSpec spec = mapper.readValue(yaml, NaftikoSpec.class); Capability capability = new Capability(spec); - ApiServerAdapter adapter = (ApiServerAdapter) capability.getServerAdapters().get(0); - ApiServerSpec serverSpec = (ApiServerSpec) adapter.getSpec(); - ApiServerResourceSpec resourceSpec = serverSpec.getResources().get(0); - ApiResourceRestlet restlet = new ApiResourceRestlet(capability, serverSpec, resourceSpec); + RestServerAdapter adapter = (RestServerAdapter) capability.getServerAdapters().get(0); + RestServerSpec serverSpec = (RestServerSpec) adapter.getSpec(); + RestServerResourceSpec resourceSpec = serverSpec.getResources().get(0); + RestResourceRestlet restlet = new RestResourceRestlet(capability, serverSpec, resourceSpec); Request request = new Request(org.restlet.data.Method.GET, "http://localhost/notion/pages"); request.getAttributes().put("path", "pages"); Response response = new Response(request); - Method forwardMethod = ApiResourceRestlet.class.getDeclaredMethod("handleFromForwardSpec", + Method forwardMethod = RestResourceRestlet.class.getDeclaredMethod("handleFromForwardSpec", Request.class, Response.class); forwardMethod.setAccessible(true); boolean handled = (boolean) forwardMethod.invoke(restlet, request, response); diff --git a/src/test/java/io/naftiko/engine/CapabilityForwardValueFieldTest.java b/src/test/java/io/naftiko/engine/CapabilityForwardValueFieldTest.java index 0f55820..cf7e0d8 100644 --- a/src/test/java/io/naftiko/engine/CapabilityForwardValueFieldTest.java +++ b/src/test/java/io/naftiko/engine/CapabilityForwardValueFieldTest.java @@ -20,7 +20,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; import io.naftiko.Capability; -import io.naftiko.engine.consumes.HttpClientAdapter; +import io.naftiko.engine.consumes.http.HttpClientAdapter; import io.naftiko.spec.NaftikoSpec; import io.naftiko.spec.InputParameterSpec; import org.restlet.Request; diff --git a/src/test/java/io/naftiko/engine/CapabilityHeaderQueryIntegrationTest.java b/src/test/java/io/naftiko/engine/CapabilityHeaderQueryIntegrationTest.java index f5649fd..d523714 100644 --- a/src/test/java/io/naftiko/engine/CapabilityHeaderQueryIntegrationTest.java +++ b/src/test/java/io/naftiko/engine/CapabilityHeaderQueryIntegrationTest.java @@ -20,13 +20,13 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; import io.naftiko.Capability; -import io.naftiko.engine.consumes.HttpClientAdapter; +import io.naftiko.engine.consumes.http.HttpClientAdapter; import io.naftiko.engine.exposes.OperationStepExecutor; -import io.naftiko.engine.exposes.ApiServerAdapter; +import io.naftiko.engine.exposes.rest.RestServerAdapter; import io.naftiko.spec.NaftikoSpec; -import io.naftiko.spec.exposes.ApiServerOperationSpec; -import io.naftiko.spec.exposes.ApiServerResourceSpec; -import io.naftiko.spec.exposes.ApiServerSpec; +import io.naftiko.spec.exposes.rest.RestServerOperationSpec; +import io.naftiko.spec.exposes.rest.RestServerResourceSpec; +import io.naftiko.spec.exposes.rest.RestServerSpec; import io.naftiko.spec.InputParameterSpec; import org.restlet.Request; import org.restlet.data.Method; @@ -37,8 +37,8 @@ public class CapabilityHeaderQueryIntegrationTest { private Capability capability; - private ApiServerSpec serverSpec; - private ApiServerResourceSpec resourceSpec; + private RestServerSpec serverSpec; + private RestServerResourceSpec resourceSpec; @BeforeEach public void setUp() throws Exception { @@ -53,14 +53,14 @@ public void setUp() throws Exception { capability = new Capability(spec); - ApiServerAdapter adapter = (ApiServerAdapter) capability.getServerAdapters().get(0); - serverSpec = (ApiServerSpec) adapter.getSpec(); + RestServerAdapter adapter = (RestServerAdapter) capability.getServerAdapters().get(0); + serverSpec = (RestServerSpec) adapter.getSpec(); resourceSpec = serverSpec.getResources().get(0); } @Test public void testHeadersAndQueryPopulation() throws Exception { - ApiServerOperationSpec serverOp = resourceSpec.getOperations().get(0); + RestServerOperationSpec serverOp = resourceSpec.getOperations().get(0); String incomingJson = "{\"user\":{\"id\":\"999\"}}"; Request req = new Request(Method.POST, "/search"); diff --git a/src/test/java/io/naftiko/engine/CapabilityHttpBodyIntegrationTest.java b/src/test/java/io/naftiko/engine/CapabilityHttpBodyIntegrationTest.java index 53fdbda..e5dd484 100644 --- a/src/test/java/io/naftiko/engine/CapabilityHttpBodyIntegrationTest.java +++ b/src/test/java/io/naftiko/engine/CapabilityHttpBodyIntegrationTest.java @@ -21,11 +21,11 @@ import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; import io.naftiko.Capability; import io.naftiko.engine.exposes.OperationStepExecutor; -import io.naftiko.engine.exposes.ApiServerAdapter; +import io.naftiko.engine.exposes.rest.RestServerAdapter; import io.naftiko.spec.NaftikoSpec; -import io.naftiko.spec.exposes.ApiServerOperationSpec; -import io.naftiko.spec.exposes.ApiServerResourceSpec; -import io.naftiko.spec.exposes.ApiServerSpec; +import io.naftiko.spec.exposes.rest.RestServerOperationSpec; +import io.naftiko.spec.exposes.rest.RestServerResourceSpec; +import io.naftiko.spec.exposes.rest.RestServerSpec; import org.restlet.Request; import org.restlet.data.Method; import org.restlet.data.MediaType; @@ -35,8 +35,8 @@ public class CapabilityHttpBodyIntegrationTest { private Capability capability; - private ApiServerSpec serverSpec; - private ApiServerResourceSpec resourceSpec; + private RestServerSpec serverSpec; + private RestServerResourceSpec resourceSpec; @BeforeEach public void setUp() throws Exception { @@ -52,14 +52,14 @@ public void setUp() throws Exception { capability = new Capability(spec); // locate ApiResourceSpec - ApiServerAdapter adapter = (ApiServerAdapter) capability.getServerAdapters().get(0); - serverSpec = (ApiServerSpec) adapter.getSpec(); + RestServerAdapter adapter = (RestServerAdapter) capability.getServerAdapters().get(0); + serverSpec = (RestServerSpec) adapter.getSpec(); resourceSpec = serverSpec.getResources().get(0); } @Test public void testClientRequestBodyTemplating() throws Exception { - ApiServerOperationSpec serverOp = resourceSpec.getOperations().get(0); + RestServerOperationSpec serverOp = resourceSpec.getOperations().get(0); // Build incoming request body String incomingJson = "{\"user\":{\"id\":\"123\",\"name\":\"Alice\"}}"; diff --git a/src/test/java/io/naftiko/engine/CapabilityMcpIntegrationTest.java b/src/test/java/io/naftiko/engine/CapabilityMcpIntegrationTest.java index 67255d5..719ce63 100644 --- a/src/test/java/io/naftiko/engine/CapabilityMcpIntegrationTest.java +++ b/src/test/java/io/naftiko/engine/CapabilityMcpIntegrationTest.java @@ -21,12 +21,12 @@ import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; import io.modelcontextprotocol.spec.McpSchema; import io.naftiko.Capability; -import io.naftiko.engine.exposes.McpServerAdapter; +import io.naftiko.engine.consumes.http.HttpClientAdapter; import io.naftiko.engine.exposes.ServerAdapter; -import io.naftiko.engine.consumes.HttpClientAdapter; +import io.naftiko.engine.exposes.mcp.McpServerAdapter; import io.naftiko.spec.NaftikoSpec; -import io.naftiko.spec.exposes.McpServerSpec; -import io.naftiko.spec.exposes.McpServerToolSpec; +import io.naftiko.spec.exposes.mcp.McpServerSpec; +import io.naftiko.spec.exposes.mcp.McpServerToolSpec; import java.io.File; /** diff --git a/src/test/java/io/naftiko/engine/CapabilityMcpResourcesPromptsIntegrationTest.java b/src/test/java/io/naftiko/engine/CapabilityMcpResourcesPromptsIntegrationTest.java index 8299c5e..edd70a4 100644 --- a/src/test/java/io/naftiko/engine/CapabilityMcpResourcesPromptsIntegrationTest.java +++ b/src/test/java/io/naftiko/engine/CapabilityMcpResourcesPromptsIntegrationTest.java @@ -22,14 +22,14 @@ import com.fasterxml.jackson.databind.node.ObjectNode; import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; import io.naftiko.Capability; -import io.naftiko.engine.exposes.McpPromptHandler; -import io.naftiko.engine.exposes.McpResourceHandler; -import io.naftiko.engine.exposes.McpServerAdapter; +import io.naftiko.engine.exposes.mcp.McpPromptHandler; +import io.naftiko.engine.exposes.mcp.McpResourceHandler; +import io.naftiko.engine.exposes.mcp.McpServerAdapter; import io.naftiko.spec.NaftikoSpec; -import io.naftiko.spec.exposes.McpServerPromptSpec; -import io.naftiko.spec.exposes.McpServerResourceSpec; -import io.naftiko.spec.exposes.McpServerSpec; -import io.naftiko.spec.exposes.McpServerToolSpec; +import io.naftiko.spec.exposes.mcp.McpServerPromptSpec; +import io.naftiko.spec.exposes.mcp.McpServerResourceSpec; +import io.naftiko.spec.exposes.mcp.McpServerSpec; +import io.naftiko.spec.exposes.mcp.McpServerToolSpec; import java.io.File; import java.util.List; import java.util.Map; @@ -583,7 +583,7 @@ public void testPromptsGetMissingNameReturnsError() throws Exception { private ObjectNode dispatch(String requestJson) throws Exception { JsonNode request = jsonMapper.readTree(requestJson); - var dispatcher = new io.naftiko.engine.exposes.McpProtocolDispatcher(adapter); + var dispatcher = new io.naftiko.engine.exposes.mcp.McpProtocolDispatcher(adapter); return dispatcher.dispatch(request); } } diff --git a/src/test/java/io/naftiko/engine/CapabilityMcpStdioIntegrationTest.java b/src/test/java/io/naftiko/engine/CapabilityMcpStdioIntegrationTest.java index 38d2d11..bf707cb 100644 --- a/src/test/java/io/naftiko/engine/CapabilityMcpStdioIntegrationTest.java +++ b/src/test/java/io/naftiko/engine/CapabilityMcpStdioIntegrationTest.java @@ -25,12 +25,12 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; import io.naftiko.Capability; -import io.naftiko.engine.exposes.McpProtocolDispatcher; -import io.naftiko.engine.exposes.McpServerAdapter; import io.naftiko.engine.exposes.ServerAdapter; -import io.naftiko.engine.exposes.StdioJsonRpcHandler; +import io.naftiko.engine.exposes.mcp.McpProtocolDispatcher; +import io.naftiko.engine.exposes.mcp.McpServerAdapter; +import io.naftiko.engine.exposes.mcp.McpStdioHandler; import io.naftiko.spec.NaftikoSpec; -import io.naftiko.spec.exposes.McpServerSpec; +import io.naftiko.spec.exposes.mcp.McpServerSpec; /** * Integration tests for MCP Server Adapter with stdio transport. @@ -188,7 +188,7 @@ public void testStdioHandlerEndToEnd() throws Exception { input.getBytes(StandardCharsets.UTF_8)); ByteArrayOutputStream out = new ByteArrayOutputStream(); - StdioJsonRpcHandler handler = new StdioJsonRpcHandler(dispatcher, in, out); + McpStdioHandler handler = new McpStdioHandler(dispatcher, in, out); handler.run(); // Runs synchronously since input is finite String output = out.toString(StandardCharsets.UTF_8); diff --git a/src/test/java/io/naftiko/engine/CapabilityProtobufIntegrationTest.java b/src/test/java/io/naftiko/engine/CapabilityProtobufIntegrationTest.java index 7bde214..74a0868 100644 --- a/src/test/java/io/naftiko/engine/CapabilityProtobufIntegrationTest.java +++ b/src/test/java/io/naftiko/engine/CapabilityProtobufIntegrationTest.java @@ -24,8 +24,8 @@ import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; import io.naftiko.Capability; import io.naftiko.spec.NaftikoSpec; -import io.naftiko.spec.consumes.HttpClientSpec; -import io.naftiko.spec.exposes.ApiServerSpec; +import io.naftiko.spec.consumes.http.HttpClientSpec; +import io.naftiko.spec.exposes.rest.RestServerSpec; import java.io.File; import java.io.InputStream; @@ -154,11 +154,11 @@ public void testCapabilityProtobufIntegration() { var exposes = spec.getCapability().getExposes(); assertEquals(1, exposes.size(), "Should have one expose server"); - ApiServerSpec apiServer = (ApiServerSpec) exposes.get(0); - assertEquals("test-protobuf", apiServer.getNamespace(), + RestServerSpec restServer = (RestServerSpec) exposes.get(0); + assertEquals("test-protobuf", restServer.getNamespace(), "Server namespace should be test-protobuf"); - var resources = apiServer.getResources(); + var resources = restServer.getResources(); assertEquals(1, resources.size(), "Should have one resource"); assertEquals("/proto/records", resources.get(0).getPath(), "Resource path should be /proto/records"); diff --git a/src/test/java/io/naftiko/engine/CapabilityApiAuthenticationIntegrationTest.java b/src/test/java/io/naftiko/engine/CapabilityRestAuthenticationIntegrationTest.java similarity index 95% rename from src/test/java/io/naftiko/engine/CapabilityApiAuthenticationIntegrationTest.java rename to src/test/java/io/naftiko/engine/CapabilityRestAuthenticationIntegrationTest.java index a12ca86..378ca79 100644 --- a/src/test/java/io/naftiko/engine/CapabilityApiAuthenticationIntegrationTest.java +++ b/src/test/java/io/naftiko/engine/CapabilityRestAuthenticationIntegrationTest.java @@ -27,10 +27,10 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; import io.naftiko.Capability; -import io.naftiko.engine.exposes.ApiServerAdapter; +import io.naftiko.engine.exposes.rest.RestServerAdapter; import io.naftiko.spec.NaftikoSpec; -public class CapabilityApiAuthenticationIntegrationTest { +public class CapabilityRestAuthenticationIntegrationTest { @Test public void bearerAuthenticationShouldReturnUnauthorizedWithoutTokenAndOkWithToken() @@ -42,7 +42,7 @@ public void bearerAuthenticationShouldReturnUnauthorizedWithoutTokenAndOkWithTok description: "Auth test" capability: exposes: - - type: "api" + - type: "rest" address: "localhost" port: 0 namespace: "sample" @@ -92,7 +92,7 @@ public void apiKeyAuthenticationShouldReturnUnauthorizedWithoutHeaderAndOkWithHe description: "Auth test" capability: exposes: - - type: "api" + - type: "rest" address: "localhost" port: 0 namespace: "sample" @@ -135,7 +135,7 @@ private Restlet buildRootRestlet(String yaml) throws Exception { NaftikoSpec spec = mapper.readValue(yaml, NaftikoSpec.class); Capability capability = new Capability(spec); - ApiServerAdapter adapter = (ApiServerAdapter) capability.getServerAdapters().get(0); + RestServerAdapter adapter = (RestServerAdapter) capability.getServerAdapters().get(0); return adapter.getServer().getNext(); } } \ No newline at end of file diff --git a/src/test/java/io/naftiko/engine/CapabilitySkillIntegrationTest.java b/src/test/java/io/naftiko/engine/CapabilitySkillIntegrationTest.java index 16160d2..3a8fa82 100644 --- a/src/test/java/io/naftiko/engine/CapabilitySkillIntegrationTest.java +++ b/src/test/java/io/naftiko/engine/CapabilitySkillIntegrationTest.java @@ -29,9 +29,9 @@ import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; import io.naftiko.Capability; import io.naftiko.engine.exposes.ServerAdapter; -import io.naftiko.engine.exposes.SkillServerAdapter; +import io.naftiko.engine.exposes.skill.SkillServerAdapter; import io.naftiko.spec.NaftikoSpec; -import io.naftiko.spec.exposes.SkillServerSpec; +import io.naftiko.spec.exposes.skill.SkillServerSpec; /** * Integration tests for the Skill Server Adapter. @@ -169,7 +169,7 @@ public void testGetSkillDetail() throws Exception { assertNotNull(invRef); assertEquals("orders-rest", invRef.get("targetNamespace")); assertEquals("list-orders", invRef.get("action")); - assertEquals("api", invRef.get("mode")); + assertEquals("rest", invRef.get("mode")); // Instruction tool has instruction path Map instructionTool = tools.get(1); diff --git a/src/test/java/io/naftiko/engine/DocumentationMetadataTest.java b/src/test/java/io/naftiko/engine/DocumentationMetadataTest.java index 86aa4fa..aed6eb3 100644 --- a/src/test/java/io/naftiko/engine/DocumentationMetadataTest.java +++ b/src/test/java/io/naftiko/engine/DocumentationMetadataTest.java @@ -23,10 +23,10 @@ import io.naftiko.spec.DocumentationMetadata; import io.naftiko.spec.InputParameterSpec; import io.naftiko.spec.OutputParameterSpec; -import io.naftiko.spec.exposes.ApiServerOperationSpec; -import io.naftiko.spec.exposes.ApiServerResourceSpec; -import io.naftiko.spec.exposes.ApiServerStepSpec; import io.naftiko.spec.exposes.ServerCallSpec; +import io.naftiko.spec.exposes.rest.RestServerOperationSpec; +import io.naftiko.spec.exposes.rest.RestServerResourceSpec; +import io.naftiko.spec.exposes.rest.RestServerStepSpec; import io.naftiko.spec.exposes.OperationStepCallSpec; import static org.junit.jupiter.api.Assertions.*; @@ -37,14 +37,14 @@ */ public class DocumentationMetadataTest { - private ApiServerResourceSpec resource; - private ApiServerOperationSpec operation; + private RestServerResourceSpec resource; + private RestServerOperationSpec operation; @BeforeEach public void setUp() { - resource = new ApiServerResourceSpec("/users", null, null, "User management endpoints", null); + resource = new RestServerResourceSpec("/users", null, null, "User management endpoints", null); - operation = new ApiServerOperationSpec(resource, "GET", "getUser", "Get User"); + operation = new RestServerOperationSpec(resource, "GET", "getUser", "Get User"); operation.setDescription("Retrieves a user by ID"); } @@ -60,11 +60,11 @@ public void testExtractResourceDocumentation() { @Test public void testExtractResourceDocumentationWithMultipleOperations() { - ApiServerOperationSpec op1 = new ApiServerOperationSpec(resource, "GET", "list", "List Users"); + RestServerOperationSpec op1 = new RestServerOperationSpec(resource, "GET", "list", "List Users"); op1.setDescription("List all users"); resource.getOperations().add(op1); - ApiServerOperationSpec op2 = new ApiServerOperationSpec(resource, "POST", "create", "Create User"); + RestServerOperationSpec op2 = new RestServerOperationSpec(resource, "POST", "create", "Create User"); op2.setDescription("Create a new user"); resource.getOperations().add(op2); @@ -108,14 +108,14 @@ public void testExtractParameterDocumentation() { @Test public void testExtractStepDocumentation() { - List steps = new ArrayList<>(); + List steps = new ArrayList<>(); ServerCallSpec call1 = new ServerCallSpec("users.get", null, "Fetch user details"); - ApiServerStepSpec step1 = new ApiServerStepSpec(call1, null, "Retrieve user information"); + RestServerStepSpec step1 = new RestServerStepSpec(call1, null, "Retrieve user information"); steps.add(step1); ServerCallSpec call2 = new ServerCallSpec("users.audit", null); - ApiServerStepSpec step2 = new ApiServerStepSpec(call2, null, "Log the access"); + RestServerStepSpec step2 = new RestServerStepSpec(call2, null, "Log the access"); steps.add(step2); List> stepDocs = DocumentationMetadata.extractStepDocumentation(steps); @@ -151,9 +151,9 @@ public void testFormatOperationDocumentation() { } @Test - public void testApiServerStepSpecWithDescription() { + public void testRestServerStepSpecWithDescription() { ServerCallSpec call = new ServerCallSpec("getUser"); - ApiServerStepSpec step = new ApiServerStepSpec(call, null, "Fetch user by ID"); + RestServerStepSpec step = new RestServerStepSpec(call, null, "Fetch user by ID"); assertEquals("Fetch user by ID", step.getDescription()); } @@ -167,7 +167,7 @@ public void testOperationStepCallSpecWithName() { } @Test - public void testApiServerCallSpecWithDescription() { + public void testRestServerCallSpecWithDescription() { ServerCallSpec call = new ServerCallSpec("users.get", new HashMap<>(), "Retrieve a user"); assertEquals("Retrieve a user", call.getDescription()); diff --git a/src/test/java/io/naftiko/engine/consumes/HttpClientAdapterAuthTest.java b/src/test/java/io/naftiko/engine/consumes/HttpClientAdapterAuthTest.java index 7d364ea..01ab4b4 100644 --- a/src/test/java/io/naftiko/engine/consumes/HttpClientAdapterAuthTest.java +++ b/src/test/java/io/naftiko/engine/consumes/HttpClientAdapterAuthTest.java @@ -20,8 +20,9 @@ import org.junit.jupiter.api.Test; import org.restlet.Request; import org.restlet.data.Method; -import io.naftiko.spec.consumes.BearerAuthenticationSpec; -import io.naftiko.spec.consumes.HttpClientSpec; +import io.naftiko.engine.consumes.http.HttpClientAdapter; +import io.naftiko.spec.consumes.http.HttpBearerAuthenticationSpec; +import io.naftiko.spec.consumes.http.HttpClientSpec; public class HttpClientAdapterAuthTest { @@ -29,7 +30,7 @@ public class HttpClientAdapterAuthTest { public void bearerAuthenticationShouldSetAuthorizationHeader() { HttpClientSpec spec = new HttpClientSpec("notion", "https://api.notion.com/v1/", null); - BearerAuthenticationSpec authentication = new BearerAuthenticationSpec(); + HttpBearerAuthenticationSpec authentication = new HttpBearerAuthenticationSpec(); authentication.setType("bearer"); authentication.setToken("{{notion_api_key}}"); spec.setAuthentication(authentication); diff --git a/src/test/java/io/naftiko/engine/consumes/HttpClientAdapterHeadersTest.java b/src/test/java/io/naftiko/engine/consumes/HttpClientAdapterHeadersTest.java index 166bf8c..ab74fd2 100644 --- a/src/test/java/io/naftiko/engine/consumes/HttpClientAdapterHeadersTest.java +++ b/src/test/java/io/naftiko/engine/consumes/HttpClientAdapterHeadersTest.java @@ -21,8 +21,9 @@ import org.restlet.Request; import org.restlet.data.Method; import io.naftiko.engine.Resolver; +import io.naftiko.engine.consumes.http.HttpClientAdapter; import io.naftiko.spec.InputParameterSpec; -import io.naftiko.spec.consumes.HttpClientSpec; +import io.naftiko.spec.consumes.http.HttpClientSpec; public class HttpClientAdapterHeadersTest { diff --git a/src/test/java/io/naftiko/engine/exposes/ApiOperationsRestletTest.java b/src/test/java/io/naftiko/engine/exposes/RestOperationsRestletTest.java similarity index 97% rename from src/test/java/io/naftiko/engine/exposes/ApiOperationsRestletTest.java rename to src/test/java/io/naftiko/engine/exposes/RestOperationsRestletTest.java index 76ef794..4a3357c 100644 --- a/src/test/java/io/naftiko/engine/exposes/ApiOperationsRestletTest.java +++ b/src/test/java/io/naftiko/engine/exposes/RestOperationsRestletTest.java @@ -20,9 +20,9 @@ import java.util.Map; /** - * Unit tests for ApiOperationsRestlet, particularly the Mustache template resolution functionality. + * Unit tests for RestResourceRestlet, particularly the Mustache template resolution functionality. */ -public class ApiOperationsRestletTest { +public class RestOperationsRestletTest { /** * Test that null template returns null. diff --git a/src/test/java/io/naftiko/engine/exposes/ApiServerAuthenticationRestletTest.java b/src/test/java/io/naftiko/engine/exposes/RestServerAuthenticationRestletTest.java similarity index 81% rename from src/test/java/io/naftiko/engine/exposes/ApiServerAuthenticationRestletTest.java rename to src/test/java/io/naftiko/engine/exposes/RestServerAuthenticationRestletTest.java index 968ac71..8bc9e3a 100644 --- a/src/test/java/io/naftiko/engine/exposes/ApiServerAuthenticationRestletTest.java +++ b/src/test/java/io/naftiko/engine/exposes/RestServerAuthenticationRestletTest.java @@ -22,14 +22,15 @@ import org.restlet.data.MediaType; import org.restlet.data.Method; import org.restlet.data.Status; -import io.naftiko.spec.consumes.ApiKeyAuthenticationSpec; -import io.naftiko.spec.consumes.BearerAuthenticationSpec; +import io.naftiko.engine.exposes.rest.RestServerAuthenticationRestlet; +import io.naftiko.spec.consumes.http.HttpApiKeyAuthenticationSpec; +import io.naftiko.spec.consumes.http.HttpBearerAuthenticationSpec; -public class ApiServerAuthenticationRestletTest { +public class RestServerAuthenticationRestletTest { @Test public void bearerShouldAuthorizeMatchingToken() { - BearerAuthenticationSpec auth = new BearerAuthenticationSpec(); + HttpBearerAuthenticationSpec auth = new HttpBearerAuthenticationSpec(); auth.setToken("token-123"); Restlet next = new Restlet() { @@ -40,7 +41,7 @@ public void handle(Request request, Response response) { } }; - ApiServerAuthenticationRestlet secured = new ApiServerAuthenticationRestlet(auth, next); + RestServerAuthenticationRestlet secured = new RestServerAuthenticationRestlet(auth, next); Request request = new Request(Method.GET, "http://localhost/test"); request.getHeaders().set("Authorization", "Bearer token-123"); Response response = new Response(request); @@ -52,7 +53,7 @@ public void handle(Request request, Response response) { @Test public void bearerShouldRejectMismatchedToken() { - BearerAuthenticationSpec auth = new BearerAuthenticationSpec(); + HttpBearerAuthenticationSpec auth = new HttpBearerAuthenticationSpec(); auth.setToken("token-123"); Restlet next = new Restlet() { @@ -60,7 +61,7 @@ public void bearerShouldRejectMismatchedToken() { public void handle(Request request, Response response) { } }; - ApiServerAuthenticationRestlet secured = new ApiServerAuthenticationRestlet(auth, next); + RestServerAuthenticationRestlet secured = new RestServerAuthenticationRestlet(auth, next); Request request = new Request(Method.GET, "http://localhost/test"); request.getHeaders().set("Authorization", "Bearer bad-token"); Response response = new Response(request); @@ -72,7 +73,7 @@ public void handle(Request request, Response response) { @Test public void apiKeyHeaderShouldAuthorizeMatchingValue() { - ApiKeyAuthenticationSpec auth = new ApiKeyAuthenticationSpec(); + HttpApiKeyAuthenticationSpec auth = new HttpApiKeyAuthenticationSpec(); auth.setKey("X-API-Key"); auth.setValue("abc123"); auth.setPlacement("header"); @@ -84,7 +85,7 @@ public void handle(Request request, Response response) { } }; - ApiServerAuthenticationRestlet secured = new ApiServerAuthenticationRestlet(auth, next); + RestServerAuthenticationRestlet secured = new RestServerAuthenticationRestlet(auth, next); Request request = new Request(Method.GET, "http://localhost/test"); request.getHeaders().set("X-API-Key", "abc123"); Response response = new Response(request); @@ -96,7 +97,7 @@ public void handle(Request request, Response response) { @Test public void apiKeyQueryShouldRejectMismatchedValue() { - ApiKeyAuthenticationSpec auth = new ApiKeyAuthenticationSpec(); + HttpApiKeyAuthenticationSpec auth = new HttpApiKeyAuthenticationSpec(); auth.setKey("api_key"); auth.setValue("abc123"); auth.setPlacement("query"); @@ -106,7 +107,7 @@ public void apiKeyQueryShouldRejectMismatchedValue() { public void handle(Request request, Response response) { } }; - ApiServerAuthenticationRestlet secured = new ApiServerAuthenticationRestlet(auth, next); + RestServerAuthenticationRestlet secured = new RestServerAuthenticationRestlet(auth, next); Request request = new Request(Method.GET, "http://localhost/test?api_key=wrong"); Response response = new Response(request); @@ -125,7 +126,7 @@ public void bearerWithoutAllowedVariablesShouldNotResolveEnvironmentVariable() { ProcessBuilder pb = new ProcessBuilder(); pb.environment().put(envVarName, envVarValue); - BearerAuthenticationSpec auth = new BearerAuthenticationSpec(); + HttpBearerAuthenticationSpec auth = new HttpBearerAuthenticationSpec(); auth.setToken("{{" + envVarName + "}}"); Restlet next = new Restlet() { @@ -136,8 +137,8 @@ public void handle(Request request, Response response) { // Create restlet WITHOUT allowed variables (empty set) // This means no external refs were declared - ApiServerAuthenticationRestlet secured = - new ApiServerAuthenticationRestlet(auth, next, Set.of()); + RestServerAuthenticationRestlet secured = + new RestServerAuthenticationRestlet(auth, next, Set.of()); Request request = new Request(Method.GET, "http://localhost/test"); request.getHeaders().set("Authorization", "Bearer secret-token-from-env"); @@ -152,7 +153,7 @@ public void handle(Request request, Response response) { @Test public void bearerWithAllowedVariablesShouldResolveOnlyDeclaredVariables() { - BearerAuthenticationSpec auth = new BearerAuthenticationSpec(); + HttpBearerAuthenticationSpec auth = new HttpBearerAuthenticationSpec(); auth.setToken("{{declared_token}}"); Restlet next = new Restlet() { @@ -165,8 +166,8 @@ public void handle(Request request, Response response) { // Create restlet WITH allowed variables set // This simulates externalRefs declaring this variable - ApiServerAuthenticationRestlet secured = - new ApiServerAuthenticationRestlet(auth, next, Set.of("declared_token")); + RestServerAuthenticationRestlet secured = + new RestServerAuthenticationRestlet(auth, next, Set.of("declared_token")); Request request = new Request(Method.GET, "http://localhost/test"); request.getHeaders().set("Authorization", "Bearer my-token-123"); @@ -183,7 +184,7 @@ public void handle(Request request, Response response) { @Test public void apiKeyWithoutAllowedVariablesShouldNotResolveEnvironmentVariable() { - ApiKeyAuthenticationSpec auth = new ApiKeyAuthenticationSpec(); + HttpApiKeyAuthenticationSpec auth = new HttpApiKeyAuthenticationSpec(); auth.setKey("X-API-Key"); auth.setValue("{{undeclared_api_key}}"); auth.setPlacement("header"); @@ -195,8 +196,8 @@ public void handle(Request request, Response response) { }; // Create restlet WITHOUT allowed variables (not declared in externalRefs) - ApiServerAuthenticationRestlet secured = - new ApiServerAuthenticationRestlet(auth, next, Set.of()); + RestServerAuthenticationRestlet secured = + new RestServerAuthenticationRestlet(auth, next, Set.of()); Request request = new Request(Method.GET, "http://localhost/test"); request.getHeaders().set("X-API-Key", "actual-key-value"); @@ -210,7 +211,7 @@ public void handle(Request request, Response response) { @Test public void apiKeyWithAllowedVariablesShouldResolveOnlyDeclaredKey() { - ApiKeyAuthenticationSpec auth = new ApiKeyAuthenticationSpec(); + HttpApiKeyAuthenticationSpec auth = new HttpApiKeyAuthenticationSpec(); auth.setKey("X-API-Key"); auth.setValue("{{my_declared_key}}"); auth.setPlacement("header"); @@ -222,8 +223,8 @@ public void handle(Request request, Response response) { }; // Create restlet WITH this variable in the allowed set - ApiServerAuthenticationRestlet secured = - new ApiServerAuthenticationRestlet(auth, next, Set.of("my_declared_key")); + RestServerAuthenticationRestlet secured = + new RestServerAuthenticationRestlet(auth, next, Set.of("my_declared_key")); Request request = new Request(Method.GET, "http://localhost/test"); request.getHeaders().set("X-API-Key", "actual-key-value"); @@ -239,7 +240,7 @@ public void handle(Request request, Response response) { @Test public void backwardCompatibilityShouldAllowNoAllowedVariablesParameter() { // Test that old code using the 2-parameter constructor still works - BearerAuthenticationSpec auth = new BearerAuthenticationSpec(); + HttpBearerAuthenticationSpec auth = new HttpBearerAuthenticationSpec(); auth.setToken("hardcoded-token"); Restlet next = new Restlet() { @@ -251,7 +252,7 @@ public void handle(Request request, Response response) { }; // Old-style instantiation without allowed variables - ApiServerAuthenticationRestlet secured = new ApiServerAuthenticationRestlet(auth, next); + RestServerAuthenticationRestlet secured = new RestServerAuthenticationRestlet(auth, next); Request request = new Request(Method.GET, "http://localhost/test"); request.getHeaders().set("Authorization", "Bearer hardcoded-token"); diff --git a/src/test/java/io/naftiko/spec/DescriptionMetadataRoundTripTest.java b/src/test/java/io/naftiko/spec/DescriptionMetadataRoundTripTest.java index 6fb7671..47bdbe4 100644 --- a/src/test/java/io/naftiko/spec/DescriptionMetadataRoundTripTest.java +++ b/src/test/java/io/naftiko/spec/DescriptionMetadataRoundTripTest.java @@ -18,10 +18,8 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; - -import io.naftiko.spec.exposes.ApiServerStepSpec; import io.naftiko.spec.exposes.ServerCallSpec; - +import io.naftiko.spec.exposes.rest.RestServerStepSpec; import static org.junit.jupiter.api.Assertions.*; /** @@ -40,15 +38,15 @@ public void setUp() { } @Test - public void testApiServerStepSpecDescriptionYamlRoundTrip() throws Exception { + public void testRestServerStepSpecDescriptionYamlRoundTrip() throws Exception { ServerCallSpec call = new ServerCallSpec("users.fetch", null, "Retrieves user data"); - ApiServerStepSpec step = new ApiServerStepSpec(call, null, "Fetch user information"); + RestServerStepSpec step = new RestServerStepSpec(call, null, "Fetch user information"); // Serialize to YAML string String yaml = yamlMapper.writeValueAsString(step); // Deserialize back - ApiServerStepSpec restored = yamlMapper.readValue(yaml, ApiServerStepSpec.class); + RestServerStepSpec restored = yamlMapper.readValue(yaml, RestServerStepSpec.class); assertEquals("Fetch user information", restored.getDescription()); assertNotNull(restored.getCall()); @@ -57,7 +55,7 @@ public void testApiServerStepSpecDescriptionYamlRoundTrip() throws Exception { } @Test - public void testApiServerCallSpecDescriptionYamlRoundTrip() throws Exception { + public void testRestServerCallSpecDescriptionYamlRoundTrip() throws Exception { ServerCallSpec call = new ServerCallSpec("users.delete", null, "Remove a user permanently"); // Serialize to YAML string @@ -71,22 +69,22 @@ public void testApiServerCallSpecDescriptionYamlRoundTrip() throws Exception { } @Test - public void testApiServerStepSpecDescriptionJsonRoundTrip() throws Exception { + public void testRestServerStepSpecDescriptionJsonRoundTrip() throws Exception { ServerCallSpec call = new ServerCallSpec("logs.write", null); - ApiServerStepSpec step = new ApiServerStepSpec(call, null, "Write audit log"); + RestServerStepSpec step = new RestServerStepSpec(call, null, "Write audit log"); // Serialize to JSON string String json = jsonMapper.writeValueAsString(step); // Deserialize back - ApiServerStepSpec restored = jsonMapper.readValue(json, ApiServerStepSpec.class); + RestServerStepSpec restored = jsonMapper.readValue(json, RestServerStepSpec.class); assertEquals("Write audit log", restored.getDescription()); assertEquals("logs.write", restored.getCall().getOperation()); } @Test - public void testApiServerCallSpecWithoutDescriptionYamlRoundTrip() throws Exception { + public void testRestServerCallSpecWithoutDescriptionYamlRoundTrip() throws Exception { ServerCallSpec call = new ServerCallSpec("users.get"); // Serialize to YAML string @@ -101,7 +99,7 @@ public void testApiServerCallSpecWithoutDescriptionYamlRoundTrip() throws Except @Test public void testDescriptionExcludedWhenNullInSerialization() throws Exception { - ApiServerStepSpec step = new ApiServerStepSpec(new ServerCallSpec("test"), null, null); + RestServerStepSpec step = new RestServerStepSpec(new ServerCallSpec("test"), null, null); // Serialize to YAML String yaml = yamlMapper.writeValueAsString(step); @@ -113,7 +111,7 @@ public void testDescriptionExcludedWhenNullInSerialization() throws Exception { @Test public void testDescriptionIncludedWhenPresentInSerialization() throws Exception { - ApiServerStepSpec step = new ApiServerStepSpec(new ServerCallSpec("test"), null, "Test operation"); + RestServerStepSpec step = new RestServerStepSpec(new ServerCallSpec("test"), null, "Test operation"); // Serialize to YAML String yaml = yamlMapper.writeValueAsString(step); @@ -129,7 +127,7 @@ public void testMultipleStepsWithDescriptionsYamlRoundTrip() throws Exception { String yamlContent = "call:\n operation: users.get\n description: Fetch user\n" + "description: Get user step\n"; - ApiServerStepSpec step = yamlMapper.readValue(yamlContent, ApiServerStepSpec.class); + RestServerStepSpec step = yamlMapper.readValue(yamlContent, RestServerStepSpec.class); assertEquals("Get user step", step.getDescription()); assertEquals("users.get", step.getCall().getOperation()); diff --git a/src/test/java/io/naftiko/spec/DocumentationMetadata.java b/src/test/java/io/naftiko/spec/DocumentationMetadata.java index 33041a9..80143f1 100644 --- a/src/test/java/io/naftiko/spec/DocumentationMetadata.java +++ b/src/test/java/io/naftiko/spec/DocumentationMetadata.java @@ -16,10 +16,10 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import io.naftiko.spec.exposes.ApiServerOperationSpec; -import io.naftiko.spec.exposes.ApiServerResourceSpec; -import io.naftiko.spec.exposes.ApiServerStepSpec; import io.naftiko.spec.exposes.OperationStepSpec; +import io.naftiko.spec.exposes.rest.RestServerOperationSpec; +import io.naftiko.spec.exposes.rest.RestServerResourceSpec; +import io.naftiko.spec.exposes.rest.RestServerStepSpec; import io.naftiko.spec.exposes.OperationStepCallSpec; /** @@ -34,7 +34,7 @@ public class DocumentationMetadata { * @param resource The resource specification * @return Map containing resource documentation */ - public static Map extractResourceDocumentation(ApiServerResourceSpec resource) { + public static Map extractResourceDocumentation(RestServerResourceSpec resource) { Map docs = new HashMap<>(); if (resource != null) { @@ -43,9 +43,9 @@ public static Map extractResourceDocumentation(ApiServerResource // Extract operation descriptions Map operations = new HashMap<>(); - List ops = resource.getOperations(); + List ops = resource.getOperations(); if (ops != null) { - for (ApiServerOperationSpec op : ops) { + for (RestServerOperationSpec op : ops) { if (op != null && op.getName() != null) { operations.put(op.getName(), op.getDescription() != null ? op.getDescription() : ""); } @@ -104,12 +104,12 @@ public static Map extractParameterDocumentation( * @param steps List of operation steps * @return List of step documentation with descriptions */ - public static List> extractStepDocumentation(List steps) { + public static List> extractStepDocumentation(List steps) { List> stepDocs = new java.util.ArrayList<>(); if (steps != null) { for (int i = 0; i < steps.size(); i++) { - ApiServerStepSpec step = steps.get(i); + RestServerStepSpec step = steps.get(i); if (step != null) { Map stepDoc = new HashMap<>(); stepDoc.put("index", i); @@ -169,8 +169,8 @@ public static List> extractStepDocumentationFromOperationSte * @param operation The operation specification * @return Formatted documentation string */ - public static String formatOperationDocumentation(ApiServerResourceSpec resource, - ApiServerOperationSpec operation) { + public static String formatOperationDocumentation(RestServerResourceSpec resource, + RestServerOperationSpec operation) { StringBuilder doc = new StringBuilder(); if (resource != null && operation != null) { diff --git a/src/test/java/io/naftiko/spec/ParentResourceDeserializationTest.java b/src/test/java/io/naftiko/spec/ParentResourceDeserializationTest.java index a90f9f7..11b4fe5 100644 --- a/src/test/java/io/naftiko/spec/ParentResourceDeserializationTest.java +++ b/src/test/java/io/naftiko/spec/ParentResourceDeserializationTest.java @@ -16,8 +16,8 @@ import org.junit.jupiter.api.Test; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; -import io.naftiko.spec.consumes.HttpClientResourceSpec; -import io.naftiko.spec.consumes.HttpClientSpec; +import io.naftiko.spec.consumes.http.HttpClientResourceSpec; +import io.naftiko.spec.consumes.http.HttpClientSpec; import static org.junit.jupiter.api.Assertions.*; /** diff --git a/src/test/java/io/naftiko/spec/ApiServerAuthenticationDeserializationTest.java b/src/test/java/io/naftiko/spec/RestServerAuthenticationDeserializationTest.java similarity index 70% rename from src/test/java/io/naftiko/spec/ApiServerAuthenticationDeserializationTest.java rename to src/test/java/io/naftiko/spec/RestServerAuthenticationDeserializationTest.java index 2e03abe..2857d7d 100644 --- a/src/test/java/io/naftiko/spec/ApiServerAuthenticationDeserializationTest.java +++ b/src/test/java/io/naftiko/spec/RestServerAuthenticationDeserializationTest.java @@ -20,14 +20,14 @@ import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; -import io.naftiko.spec.consumes.ApiKeyAuthenticationSpec; -import io.naftiko.spec.consumes.BearerAuthenticationSpec; -import io.naftiko.spec.exposes.ApiServerSpec; +import io.naftiko.spec.consumes.http.HttpApiKeyAuthenticationSpec; +import io.naftiko.spec.consumes.http.HttpBearerAuthenticationSpec; +import io.naftiko.spec.exposes.rest.RestServerSpec; -public class ApiServerAuthenticationDeserializationTest { +public class RestServerAuthenticationDeserializationTest { @Test - public void shouldDeserializeApiServerBearerAuthentication() throws Exception { + public void shouldDeserializeRestServerBearerAuthentication() throws Exception { String yaml = """ naftiko: 0.4 info: @@ -35,7 +35,7 @@ public void shouldDeserializeApiServerBearerAuthentication() throws Exception { description: Test capability: exposes: - - type: api + - type: rest namespace: test port: 8080 authentication: @@ -52,17 +52,17 @@ public void shouldDeserializeApiServerBearerAuthentication() throws Exception { mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); NaftikoSpec spec = mapper.readValue(yaml, NaftikoSpec.class); - ApiServerSpec apiServer = (ApiServerSpec) spec.getCapability().getExposes().get(0); + RestServerSpec restServer = (RestServerSpec) spec.getCapability().getExposes().get(0); - assertNotNull(apiServer.getAuthentication(), "Authentication should be present"); - assertInstanceOf(BearerAuthenticationSpec.class, apiServer.getAuthentication(), + assertNotNull(restServer.getAuthentication(), "Authentication should be present"); + assertInstanceOf(HttpBearerAuthenticationSpec.class, restServer.getAuthentication(), "Authentication should be bearer type"); - assertEquals("bearer", apiServer.getAuthentication().getType()); - assertEquals("{{api_token}}", ((BearerAuthenticationSpec) apiServer.getAuthentication()).getToken()); + assertEquals("bearer", restServer.getAuthentication().getType()); + assertEquals("{{api_token}}", ((HttpBearerAuthenticationSpec) restServer.getAuthentication()).getToken()); } @Test - public void shouldDeserializeApiServerApiKeyAuthentication() throws Exception { + public void shouldDeserializeRestServerApiKeyAuthentication() throws Exception { String yaml = """ naftiko: 0.4 info: @@ -70,7 +70,7 @@ public void shouldDeserializeApiServerApiKeyAuthentication() throws Exception { description: Test capability: exposes: - - type: api + - type: rest namespace: test port: 8080 authentication: @@ -89,12 +89,12 @@ public void shouldDeserializeApiServerApiKeyAuthentication() throws Exception { mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); NaftikoSpec spec = mapper.readValue(yaml, NaftikoSpec.class); - ApiServerSpec apiServer = (ApiServerSpec) spec.getCapability().getExposes().get(0); + RestServerSpec restServer = (RestServerSpec) spec.getCapability().getExposes().get(0); - assertNotNull(apiServer.getAuthentication(), "Authentication should be present"); - assertInstanceOf(ApiKeyAuthenticationSpec.class, apiServer.getAuthentication(), + assertNotNull(restServer.getAuthentication(), "Authentication should be present"); + assertInstanceOf(HttpApiKeyAuthenticationSpec.class, restServer.getAuthentication(), "Authentication should be api key type"); - ApiKeyAuthenticationSpec apiKey = (ApiKeyAuthenticationSpec) apiServer.getAuthentication(); + HttpApiKeyAuthenticationSpec apiKey = (HttpApiKeyAuthenticationSpec) restServer.getAuthentication(); assertEquals("apikey", apiKey.getType()); assertEquals("X-API-Key", apiKey.getKey()); assertEquals("abc123", apiKey.getValue()); diff --git a/src/test/java/io/naftiko/spec/exposes/SkillServerSpecRoundTripTest.java b/src/test/java/io/naftiko/spec/exposes/SkillServerSpecRoundTripTest.java index 170375c..88ca03d 100644 --- a/src/test/java/io/naftiko/spec/exposes/SkillServerSpecRoundTripTest.java +++ b/src/test/java/io/naftiko/spec/exposes/SkillServerSpecRoundTripTest.java @@ -22,6 +22,9 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; import io.naftiko.spec.NaftikoSpec; +import io.naftiko.spec.exposes.skill.ExposedSkillSpec; +import io.naftiko.spec.exposes.skill.SkillServerSpec; +import io.naftiko.spec.exposes.skill.SkillToolSpec; /** * Round-trip tests for {@link SkillServerSpec} — YAML deserialization, field validation, and diff --git a/src/test/java/io/naftiko/spec/exposes/SkillToolSpecDeserializationTest.java b/src/test/java/io/naftiko/spec/exposes/SkillToolSpecDeserializationTest.java index ff3dff6..71fd892 100644 --- a/src/test/java/io/naftiko/spec/exposes/SkillToolSpecDeserializationTest.java +++ b/src/test/java/io/naftiko/spec/exposes/SkillToolSpecDeserializationTest.java @@ -18,6 +18,8 @@ import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; +import io.naftiko.spec.exposes.skill.SkillToolFromSpec; +import io.naftiko.spec.exposes.skill.SkillToolSpec; /** * Deserialization tests for {@link SkillToolSpec} and {@link SkillToolFromSpec} — verifying the diff --git a/src/test/resources/avro-capability.yaml b/src/test/resources/avro-capability.yaml index d3fe87f..16afd19 100644 --- a/src/test/resources/avro-capability.yaml +++ b/src/test/resources/avro-capability.yaml @@ -12,7 +12,7 @@ info: capability: exposes: - - type: "api" + - type: "rest" address: "localhost" port: 9093 namespace: "test-avro" diff --git a/src/test/resources/csv-capability.yaml b/src/test/resources/csv-capability.yaml index 0b0a4cf..8426e95 100644 --- a/src/test/resources/csv-capability.yaml +++ b/src/test/resources/csv-capability.yaml @@ -12,7 +12,7 @@ info: capability: exposes: - - type: "api" + - type: "rest" address: "localhost" port: 9092 namespace: "test-csv" diff --git a/src/test/resources/http-body-capability.yaml b/src/test/resources/http-body-capability.yaml index 8e1cb6d..cd6c396 100644 --- a/src/test/resources/http-body-capability.yaml +++ b/src/test/resources/http-body-capability.yaml @@ -3,7 +3,7 @@ naftiko: "0.5" capability: exposes: - - type: "api" + - type: "rest" address: "localhost" port: 8084 namespace: "test-http-body" diff --git a/src/test/resources/http-forward-value-capability.yaml b/src/test/resources/http-forward-value-capability.yaml index 5907763..74bfcfc 100644 --- a/src/test/resources/http-forward-value-capability.yaml +++ b/src/test/resources/http-forward-value-capability.yaml @@ -9,7 +9,7 @@ info: capability: exposes: - - type: api + - type: rest address: localhost port: 8083 namespace: sample diff --git a/src/test/resources/http-header-query-capability.yaml b/src/test/resources/http-header-query-capability.yaml index e957df3..9b02f1d 100644 --- a/src/test/resources/http-header-query-capability.yaml +++ b/src/test/resources/http-header-query-capability.yaml @@ -3,7 +3,7 @@ naftiko: "0.5" capability: exposes: - - type: "api" + - type: "rest" address: "localhost" port: 8082 namespace: "test-http" diff --git a/src/test/resources/proto-capability.yaml b/src/test/resources/proto-capability.yaml index 2295482..340d525 100644 --- a/src/test/resources/proto-capability.yaml +++ b/src/test/resources/proto-capability.yaml @@ -12,7 +12,7 @@ info: capability: exposes: - - type: "api" + - type: "rest" address: "localhost" port: 9092 namespace: "test-protobuf" diff --git a/src/test/resources/register.capability.yml b/src/test/resources/register.capability.yml index 94d67b4..22e55e8 100644 --- a/src/test/resources/register.capability.yml +++ b/src/test/resources/register.capability.yml @@ -6,7 +6,7 @@ info: description: "Business description of your capability" capability: exposes: - - type: "api" + - type: "rest" namespace: "documentation" port: 8081 resources: diff --git a/src/test/resources/skill-capability.yaml b/src/test/resources/skill-capability.yaml index c580ed1..045539e 100644 --- a/src/test/resources/skill-capability.yaml +++ b/src/test/resources/skill-capability.yaml @@ -12,7 +12,7 @@ info: capability: exposes: - - type: "api" + - type: "rest" address: "localhost" port: 9098 namespace: "orders-rest" diff --git a/src/test/resources/xml-capability.yaml b/src/test/resources/xml-capability.yaml index d52fc5e..7f826ad 100644 --- a/src/test/resources/xml-capability.yaml +++ b/src/test/resources/xml-capability.yaml @@ -12,7 +12,7 @@ info: capability: exposes: - - type: "api" + - type: "rest" address: "localhost" port: 9091 namespace: "test-xml" diff --git a/src/test/resources/yaml-capability.yaml b/src/test/resources/yaml-capability.yaml index 57a0285..eb432a2 100644 --- a/src/test/resources/yaml-capability.yaml +++ b/src/test/resources/yaml-capability.yaml @@ -12,7 +12,7 @@ info: capability: exposes: - - type: "api" + - type: "rest" address: "localhost" port: 9092 namespace: "test-yaml"