# How to Implement Goal Export with @Export(remote = true) for Platform-Wide Discovery in Embabel

> Implement goal export with @Export(remote = true) in Embabel to enable platform-wide goal discovery. Convert agent goals into discoverable MCP tools for remote clients.

- Repository: [Embabel/embabel-agent](https://github.com/embabel/embabel-agent)
- Tags: how-to-guide
- Published: 2026-08-08

---

**Use the `export` attribute of `@AchievesGoal` with `remote = true` to automatically convert agent goals into MCP tools that any remote client can discover and invoke across the Embabel platform.**

The [embabel/embabel-agent](https://github.com/embabel/embabel-agent) framework treats every goal-achieving action as a potential remote tool. By configuring **goal export with `@Export(remote = true)`**, you transform local `@AchievesGoal` methods into platform-wide resources discoverable via the Model-Context-Protocol (MCP) server. This allows distributed clients to leverage your agent's capabilities without direct coupling to the implementation.

## Understanding the @Export Annotation Attributes

The `@Export` annotation, defined in [[`Export.java`](https://github.com/embabel/embabel-agent/blob/main/Export.java)](https://github.com/embabel/embabel-agent/blob/main/embabel-agent-api/src/main/java/com/embabel/agent/api/annotation/Export.java), controls how goals are exposed through the `export` attribute of [`AchievesGoal`](https://github.com/embabel/embabel-agent/blob/main/embabel-agent-api/src/main/java/com/embabel/agent/api/annotation/AchievesGoal.java). The annotation supports four key attributes:

- **`remote`** – When set to `true`, the framework wraps the goal in an **AgentTool** and registers it with the MCP server for cross-platform discovery.
- **`local`** – When `true` (default), the goal remains usable within the same agent process.
- **`name`** – Overrides the automatically generated tool name used in MCP tool listings.
- **`startingInputTypes`** – Declares input types (e.g., `UserInput.class`) that remote clients must provide when invoking the tool.

## How Platform-Wide Export Works

The export mechanism follows a four-stage pipeline implemented in the framework's annotation processing layer:

1. **Agent Scanning** – The framework scans classes annotated with `@Agent` to identify methods marked with `@AchievesGoal`.
2. **Goal Instantiation** – For each annotated method, the system creates a `Goal` object representing the logical objective.
3. **Tool Conversion** – If `export = @Export(remote = true)` is present, the goal is automatically converted into an `AgentTool` and bound to the **MCP server**, the central discovery service.
4. **Remote Discovery** – Clients query the MCP server to retrieve available tools, including their names and required input schemas, then invoke them via standard MCP request formats.

## Implementing Remote Goal Export

To expose a goal platform-wide, nest the `@Export` annotation within `@AchievesGoal` and set `remote = true`.

### Java Implementation

The following agent demonstrates the pattern using `NewsDigest` operations:

```java
@Agent(description = "News digest generator")
@SecureAgentTool("hasAuthority('news:read')")
public class NewsDigestAgent {

    @Action
    public NewsTopic extractTopic(UserInput input, OperationContext ctx) {
        // Extraction logic
        return new NewsTopic(...);
    }

    @AchievesGoal(
        description = "Produce a curated news digest",
        export = @Export(
            remote = true,
            name = "newsDigest",
            startingInputTypes = {UserInput.class}
        )
    )
    @Action
    public NewsDigest produceDigest(NewsTopic topic, OperationContext ctx) {
        // Digest generation logic
        return new NewsDigest(...);
    }
}

```

### Kotlin Implementation

The same pattern applies in Kotlin, using array literals for `startingInputTypes`:

```kotlin
@Agent(description = "News digest generator")
@SecureAgentTool("hasAuthority('news:read')")
class NewsDigestAgent {

    @Action
    fun extractTopic(input: UserInput, ctx: OperationContext): NewsTopic {
        return NewsTopic(...)
    }

    @AchievesGoal(
        description = "Produce a curated news digest",
        export = Export(
            remote = true,
            name = "newsDigest",
            startingInputTypes = [UserInput::class]
        )
    )
    @Action
    fun produceDigest(topic: NewsTopic, ctx: OperationContext): NewsDigest {
        return NewsDigest(...)
    }
}

```

## Securing Exported Tools

When exposing goals remotely, apply the **`@SecureAgentTool`** annotation to enforce authorization. You can place this on the agent class or specific methods. The security expression (e.g., `"hasAuthority('news:read')"`) is evaluated before the tool executes, preventing unauthorized remote access to sensitive operations.

## Declaring Input Types for Remote Clients

The **`startingInputTypes`** attribute enables MCP clients to automatically generate UI prompts for required domain objects. By declaring `startingInputTypes = {UserInput.class}`, you inform remote clients that the tool expects user-provided input, allowing the client to collect this data before invoking the agent's goal.

## Validation and Testing

The framework's test suite includes examples of remote export configurations. In [[`EmbabelMockitoIntegrationTestStreamingTest.java`](https://github.com/embabel/embabel-agent/blob/main/EmbabelMockitoIntegrationTestStreamingTest.java)](https://github.com/embabel/embabel-agent/blob/main/embabel-agent-test-support/embabel-agent-test/src/test/java/com/embabel/agent/test/integration/EmbabelMockitoIntegrationTestStreamingTest.java), the following pattern validates the export mechanism:

```java
@AchievesGoal(
    description = "Write and review a story",
    export = @Export(remote = true, name = "writeAndReviewStory")
)
@Action
public StoryResult writeAndReviewStory(UserInput input, OperationContext ctx) {
    // Implementation
}

```

## Summary

- **Goal export with `@Export(remote = true)`** converts `@AchievesGoal` methods into MCP tools discoverable by any platform client.
- The framework handles **automatic conversion** from `Goal` to `AgentTool` during annotation processing.
- Use **`startingInputTypes`** to declare input requirements for remote client UI generation.
- Apply **`@SecureAgentTool`** to protect exported goals from unauthorized remote invocation.
- Configuration is defined in [[`Export.java`](https://github.com/embabel/embabel-agent/blob/main/Export.java)](https://github.com/embabel/embabel-agent/blob/main/embabel-agent-api/src/main/java/com/embabel/agent/api/annotation/Export.java) and consumed by the MCP server registry.

## Frequently Asked Questions

### What is the difference between local and remote goal export?

Local export (`local = true`) makes the goal available for invocation within the same agent process, while remote export (`remote = true`) publishes the goal as an MCP tool that external clients can discover and call across the network. You can enable both simultaneously for maximum flexibility.

### How does the MCP server discover exported goals?

During application startup, the framework scans for `@Agent` classes and processes `@AchievesGoal` annotations. When `remote = true` is detected, the goal is wrapped in an `AgentTool` instance and registered with the central MCP server, which maintains a registry of all platform-wide tools.

### Can I customize the tool name shown to remote clients?

Yes. Use the **`name`** attribute inside `@Export` to override the default tool name. For example, `@Export(remote = true, name = "customToolName")` ensures remote clients see "customToolName" instead of the auto-generated name derived from the method signature.

### How do I handle security for remotely exported goals?

Add the `@SecureAgentTool` annotation to your agent class or method, providing a SpEL expression that evaluates the user's authorities. The framework checks this expression before executing the tool, ensuring only authorized clients can invoke the remotely exported goal.