> ## Documentation Index
> Fetch the complete documentation index at: https://docs.hologrow.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Use OpenAI Agents SDK with Marrow MCP

# Use OpenAI Agents SDK with Marrow MCP

This tutorial shows how to build a small TypeScript agent with the [OpenAI Agents JS SDK](https://github.com/openai/openai-agents-js) and connect it to Marrow MCP. The sample app does one practical job: it uses Marrow advertising data, downloads the export file, loads it into DuckDB and writes a JSON file with improved Amazon listing copy.

## What you will build

By the end, you will have a simple agent that:

* connects to Marrow MCP with `hostedMcpTool`
* downloads an export file before the URL expires
* loads the data into DuckDB and runs SQL over it
* produces one final JSON file in `response/`

## Prerequisites

* Completion of the [Marrow MCP Overview](/hologrow-marrow-mcp/overview) setup, with an MCP key
* An [OpenAI API key](https://platform.openai.com/api-keys) with access to `gpt-5.4-mini`
* Node.js 24 or later (required for native TypeScript support)
* yarn (bundled through Corepack; run `corepack enable` if needed)

## Step 1: Clone and install the repository

Install the project:

```bash theme={null}
git clone https://github.com/Deltologic/marrow-mcp-openai-agents-sdk.git
cd marrow-mcp-openai-agents-sdk
yarn install
```

## Step 2: Configure your keys

Copy the environment file and add both API keys:

```bash theme={null}
cp .env.example .env
```

Open `.env` and set:

* `MARROW_MCP_KEY`: your MCP key from the [Marrow integrations page](https://app.marrow.com/integrations/mcp)
* `OPENAI_API_KEY`: your OpenAI API key

The agent already knows how to reach Marrow MCP. In `src/index.ts`, it uses this configuration:

```ts theme={null}
hostedMcpTool({
    serverLabel: 'marrow',
    serverUrl: 'https://mcp.marrow.com/mcp/v1',
    headers: {
        'marrow-mcp-key': process.env.MARROW_MCP_KEY ?? ''
    }
});
```

This is the only MCP-specific wiring the app needs. The agent gets the Marrow tools through the SDK, and the key is sent as a request header.

## Step 3: Create the agent

The main agent lives in `src/index.ts`. It imports the OpenAI Agents SDK and combines Marrow MCP with a few local tools:

```ts theme={null}
import { Agent, hostedMcpTool, isOpenAIResponsesRawModelStreamEvent, run } from '@openai/agents';

import { systemPrompt } from './prompts/system.prompt.ts';
import { duckdbTools } from './tools/duckdb.tools.ts';
import { fetchTools } from './tools/fetch.tools.ts';
import { outputTools } from './tools/output.tools.ts';
import { sleepTools } from './tools/sleep.tools.ts';
```

The agent itself is small:

```ts theme={null}
const agent = new Agent({
    name: 'Data Analyst',
    instructions: systemPrompt,
    tools: [
        hostedMcpTool({
            serverLabel: 'marrow',
            serverUrl: 'https://mcp.marrow.com/mcp/v1',
            headers: {
                'marrow-mcp-key': process.env.MARROW_MCP_KEY ?? ''
            }
        }),
        ...sleepTools,
        ...fetchTools,
        ...duckdbTools,
        ...outputTools
    ],
    model: 'gpt-5.4-mini',
    modelSettings: {
        reasoning: {
            effort: 'high'
        }
    }
});
```

The important parts are:

* `hostedMcpTool(...)` exposes Marrow tools to the agent
* `fetchTools`, `duckdbTools` and `outputTools` handle the local workflow
* `systemPrompt` tells the model what to do and what not to do
* `run(...)` executes the agent and streams its output

## Step 4: Understand the helper tools

The local tools make the sample app work like a real workflow, rather than a single prompt.

### Download tool

`src/tools/fetch.tools.ts` adds `download_file_from_url`. Marrow export URLs are temporary, so the agent should fetch them right away and save them locally.

```ts theme={null}
tool({
    name: 'download_file_from_url',
    description:
        'URGENT: Export links expire quickly, call this tool IMMEDIATELY before doing anything else. It downloads the file and returns the local file path.'
});
```

This keeps the workflow stable. The model can request an export URL from Marrow MCP, then pass it to the download tool before the link expires.

### DuckDB tools

`src/tools/duckdb.tools.ts` is where the downloaded data becomes queryable:

```ts theme={null}
tool({
    name: 'load_csv',
    description: 'Loads a CSV file from the local file system into a DuckDB table.'
});
```

The file also includes:

* `load_json` for JSON or newline-delimited JSON files
* `list_tables` to inspect what is loaded
* `run_sql_query` to run standard SQL against DuckDB

This combination is the core of the tutorial. Marrow MCP supplies the export, and DuckDB lets the agent rank ASINs and inspect the data locally.

### Final output tool

`src/tools/output.tools.ts` defines `output_improved_listings`. This tool is the app's final step:

```ts theme={null}
tool({
    name: 'output_improved_listings',
    description: 'Emits the final structured JSON for all improved ASIN listings.'
});
```

The agent should not write JSON directly in its response. Instead, it calls this tool once with all improved listings. The tool then writes the result to `response/improved-listings-<timestamp>.json`.

## Step 5: Use the system prompt to guide the agent

The prompt in `src/prompts/system.prompt.ts` keeps the agent focused. It tells the model to:

* use Marrow MCP tools when it needs export data
* prefer SQL-based analysis through DuckDB
* keep marketplace-specific content in the right language
* never write JSON output directly in the chat

In practice, the agent behaves like a focused analyst rather than a generic chatbot.

## Step 6: Run the app

Start the sample with:

```bash theme={null}
yarn start
```

The app runs `src/index.ts`, streams the agent's reasoning to the terminal and finishes by writing a JSON file to `./response/`.

Typical flow:

1. The agent asks Marrow MCP for the needed export.
2. The export URL is downloaded immediately.
3. DuckDB loads the file and the agent runs SQL to find weak ASINs.
4. The model rewrites the listing copy.
5. `output_improved_listings` saves the final result.

The output file contains one item per ASIN, with the current title and bullets alongside the improved version. That makes it easy to feed into another script, a bulk edit sheet, or a later workflow.

## Use a simple mental model

If you want to adapt this pattern for another Marrow-powered agent, keep the same split:

* Marrow MCP for source data
* local tools for downloading, transforming, and validating
* one dedicated output tool for the final artifact

This structure keeps the sample easy to extend without turning the agent into a pile of prompt instructions.

## Related resources

* [Marrow MCP Overview](/hologrow-marrow-mcp/overview)
* [Marrow MCP Toolbox](https://www.marrow.com/hub/docs/marrow-bigquery/mcp-toolbox)
* [OpenAI Agents JS SDK](https://github.com/openai/openai-agents-js)

## Marrow MCP resources

Check the following resources for more information:

* MCP server URL: `https://mcp.marrow.com/mcp/v1`
* [Interactive Data Scheme](/hub/data-scheme)
* Data Scheme JSON: [https://api.marrow.com/api/v1/spec/data-scheme](https://api.marrow.com/api/v1/spec/data-scheme)
* Need help? Use the [contact form](https://forms.clickup.com/9015200219/f/8cnj2ev-38615/AOYF9I35QFOXWJQXIG?type=Form\&source=hub-mcp-openai-agents-sdk-docs)
