Deliver Apify Results to Notion
Build an Apify Actor that posts scraped results to a Notion page through MCP.
Introduction
30 Second Summary
Information gathered from the web is most useful when it reaches the place where you make decisions. Copying those results into a shared page quickly becomes repetitive.
In this project, you will deploy an Apify Actor that collects a small dataset. When the run finishes, the Actor will use an MCP connector to post a results summary onto a Notion page you choose.
What You'll Build
When your deployed Actor finishes, its scraped results appear as a new comment on your chosen Notion page.
By the end of this project, you'll have:
- A local Actor run that prints scraped records in your terminal before anything reaches the cloud.
- A deployed scraper you can start from the Apify Console. You can inspect every record in the run's dataset.
- A Notion delivery flow that posts a results comment when the Actor finishes.
- Secret Mission: An optional challenge to push your skills further.
Are there any prerequisites?
You need an Apify account on the free plan, a Notion workspace with at least one page, and Node.js 20 or newer. The first step installs the Apify CLI before you create the Actor.
Before We Start
Your Apify Actor eventually sends scraped results to a Notion page. That handoff depends on a local JavaScript runtime plus access to both services.
Node.js runs the Actor code on your computer. The project needs version 20 or newer.
Your Apify account runs the deployed Actor. Your Notion workspace provides the page that receives its comments.
In this step, get ready to:
- Verify that Node.js 20 or newer is installed with npm.
- Create an Apify account on the Free plan.
- Prepare a Notion page that can receive comments.
Check Node.js and npm
Node.js is the runtime that executes your Actor locally. The official LTS installer includes npm, which manages the packages your Actor needs.
- Press Cmd+Space on macOS or the Windows key on Windows to open system search.
- Type Terminal on macOS or PowerShell on Windows.
- Press Enter to open the selected terminal.
- Check both installed tools by running these commands:
node --version
npm --version
What do these checks show?
- The node --version command prints the installed Node.js version.
- The npm --version command confirms that npm is available in the same terminal.
✔️ I see version 20 or higher
You should see a Node.js version beginning with v20 or a higher major number. A second version number confirms that npm is ready.
Good, your local runtime can support the Actor you build in this project.
ⓧ I see an older version
Your installed Node.js version is below the project minimum. Install the current LTS release to replace it with a supported version.
- Visit the official Node.js download page.
- Select the LTS release for your operating system.
- Download the installer offered for your computer.
The installer may request permission to change your computer. This is the expected system prompt for updating Node.js.
- Run the downloaded installer.
- Approve the installation permission request if it appears.
- Follow the installer with its default options.
- Close your terminal window after installation finishes.
- Reopen Terminal or PowerShell through system search.
- Verify the updated tools by running these commands:
node --version
npm --version
What confirms the update?
The first command now prints Node.js version 20 or newer. The second command prints the installed npm version.
ⓧ Command not found
Your terminal cannot find Node.js yet. Installing the official LTS release adds Node.js plus npm to your computer.
- Visit the official Node.js download page.
- Select the LTS release for your operating system.
- Download the installer offered for your computer.
The installer may request permission to change your computer. This is the expected system prompt for adding Node.js.
- Run the downloaded installer.
- Approve the installation permission request if it appears.
- Follow the installer with its default options.
- Close your terminal window after installation finishes.
- Reopen Terminal or PowerShell through system search.
- Verify the installed tools by running these commands:
node --version
npm --version
What confirms the installation?
The first command now prints Node.js version 20 or newer. The second command prints the installed npm version.
Still seeing the wrong Node.js version?
- Close every open terminal window before checking the versions again.
- Restart your computer if the terminal still reports the previous version.
- Use the official Node.js installer again if npm is still unavailable.
- Help me troubleshoot my Node.js and npm installation.
Create your free Apify account
Apify Console is where you deploy Actors and inspect their runs. The Free plan provides enough platform access for this project.
Account setup includes a plan check, which can feel like a billing step. The Free plan requires no credit card and stops platform use when its included usage is exhausted.
You will enter account credentials only on the official Apify sign-up page. Those credentials never belong in your Actor code.
- Visit the Apify Console sign-up page.
- Enter your email address in the Email field.
- Create a secure password in the Password field.
- Select Sign up.
- Open the verification email from Apify if one arrives.
- Follow the verification link in that email.
- Sign in to Apify Console.
You land on the Apify Console Dashboard after signing in.
- Select Billing in the left panel.
- Select the Subscription tab.
- Confirm that Current subscription shows Free.
That is your cloud workspace ready. Apify can now host the Actor without adding a payment method.
Prepare your Notion comment page
The finished Actor needs a specific Notion page where it can post a summary. Creating that destination now gives you a safe page for the later connector test.
You may need to enter account credentials during this setup. They stay on the official Notion login page and never enter your Actor code.
- Visit the official Notion login page.
- Complete the login or account creation flow until your workspace sidebar is visible.
- Click New page in the sidebar.
- Enter Actor Results as the page title.
Before you test the page, do you expect your account to let you post a top-level comment?
- Hover over the top of the Actor Results page.
- Click Add comment.
- Type Ready for Actor results in the comment field.
- Post the comment using the send control beside the field.
You should see Ready for Actor results in the page discussion. You have proved that this page can receive the kind of comment your Actor sends later.
Unable to add the comment?
- Confirm that you created the page inside a workspace you can edit.
- Use a different workspace if the current page belongs to another person.
- Help me check my Notion page access.
That completes the foundation: your runtime works, your Apify account is available, and your Notion destination accepts comments.
Your accounts and local runtime are ready. Next up, you will install the Apify CLI and run your first Actor locally.
Create and Run Your Actor Locally
Your Notion delivery depends on a scraper that already produces useful output. A local run proves the scrape works before cloud deployment introduces another moving part.
In this step, you will use the Apify CLI to create an Apify Actor from a template. You will finish by seeing its scraped records in your terminal.
In this step, get ready to:
- Install the Apify CLI for local Actor development.
- Create a scraper from an Actor template.
- Run the Actor locally to see its dataset records.
Install and connect the Apify CLI
The Apify CLI creates Actor projects on your computer. It also simulates the Apify environment during local runs.
- Check whether the Apify CLI is already installed by running this command:
apify --version
What does this command do?
The command asks the Apify CLI to print its installation details. A version response confirms that your terminal can find the CLI.
✔️ I see version details
Your Apify CLI is ready. Keep this terminal available for the authentication step below.
ⓧ Command not found
The Apify CLI needs to be installed before your terminal can create an Actor. Choose your operating system below.
macOS
- Install the Apify CLI on macOS by running this command:
curl -fsSL https://apify.com/install-cli.sh | bash
What does this command do?
The command downloads Apify's official installation script over HTTPS. Your shell runs the script to install the CLI as a standalone executable.
- Start a fresh terminal session through your macOS search bar.
- Confirm the installation by running this command:
apify --version
What should I see?
You should see installation details for the Apify CLI. That response confirms that the command is available in your new terminal session.
Still seeing command not found?
Close every terminal window before starting another session. This reloads the command path updated by the installer.
You can ask for help with your macOS Apify CLI installation if the version check still fails.
Windows
- Install the Apify CLI from PowerShell by running this command:
irm https://apify.com/install-cli.ps1 | iex
What does this command do?
The command downloads Apify's official PowerShell installation script. PowerShell runs the script to install the CLI as a standalone executable.
- Start a fresh PowerShell session through your Windows search bar.
- Confirm the installation by running this command:
apify --version
What should I see?
You should see installation details for the Apify CLI. That response confirms that PowerShell can find the installed command.
Still seeing command not found?
Close every PowerShell window before starting another session. This reloads the command path updated by the installer.
You can ask for help with your Windows Apify CLI installation if the version check still fails.
Linux
- Install the Apify CLI on Linux by running this command:
curl -fsSL https://apify.com/install-cli.sh | bash
What does this command do?
The command downloads Apify's official installation script over HTTPS. Your shell runs the script to install the CLI as a standalone executable.
- Start a fresh terminal session through your application launcher.
- Confirm the installation by running this command:
apify --version
What should I see?
You should see installation details for the Apify CLI. That response confirms that the command is available in your new terminal session.
Still seeing command not found?
Close every terminal window before starting another session. This reloads the command path updated by the installer.
You can ask for help with your Linux Apify CLI installation if the version check still fails.
Authentication connects the CLI to your Apify account. The login flow supports signing in through Apify Console in your browser.
- Start the Apify login flow by running this command:
apify login
What does this command do?
The command starts authentication for your Apify account. The CLI saves the resulting credentials for later commands.
- Choose the option to sign in through Apify Console in your browser.
- Complete the sign-in using your Apify account.
- Return to the terminal after the browser confirms authentication.
- Verify the connected account by running this command:
apify info
What should I see?
You should see details for your authenticated Apify account. This proves that future CLI commands can use your account.
That is the account setup complete. Your terminal can now support both local development and the deployment work ahead.
Having trouble signing in?
Check that your browser used the same Apify account you want for this project. Repeat the login flow if the terminal does not show your account details.
You can ask for help with Apify CLI authentication with any sensitive values removed from the error details.
Create your local Actor project
An Actor template supplies a working scraper with the files it needs to run. The JavaScript Cheerio crawler template produces a small set of structured web records without requiring application code in this step.
- Move to your Desktop by running this command:
cd ~/Desktop
What does this command do?
The command moves your terminal to the Desktop directory. The Actor folder created next will be easy to find.
The creation wizard asks for the Actor name first. It then asks what kind of project you want to create.
- Prepare to enter notion-results-actor when the wizard asks for the Actor name.
- Prepare to select web scraper when the wizard asks for the Actor type.
- Prepare to choose JavaScript when the wizard asks for a programming language.
- Prepare to choose JavaScript Cheerio crawler when the wizard asks for a template.
- Prepare to select Apify when the wizard asks where to host the source code.
- Start the Actor creation wizard by running this command:
apify create
What does this command do?
- The command opens an interactive wizard for creating an Actor from a template.
- Your choices create a new notion-results-actor directory on the Desktop.
- The wizard installs the template's project dependencies inside that directory.
You should see the wizard finish without an error. Your Desktop now contains a runnable Actor project in the notion-results-actor folder.
- Move into the generated Actor directory by running this command:
cd notion-results-actor
What does this command do?
The command moves your terminal into the generated Actor directory. Apify CLI commands can now find the project's Actor configuration.
Did the template fail to finish?
Check your internet connection if the template download stops. Remove any incomplete Actor folder before restarting the wizard with the same name.
You can ask for help with the Actor creation wizard using the non-sensitive terminal output.
Run the Actor and inspect its records
A Dataset stores the structured records produced by an Actor. Local Actor runs save default dataset items under storage/datasets/default/ as one JSON file per item.
Before you run the Actor, what evidence do you expect the terminal to show when the scraper completes successfully?
- Run the template Actor from the notion-results-actor directory with this command:
apify run
What does this command do?
- The command executes the Actor on your computer with simulated Apify environment variables.
- The crawler visits the template's small set of pages.
- The Actor stores each extracted result in its local default dataset.
You should see crawler activity followed by extracted records in the terminal. The run then finishes successfully after writing the records to the local dataset.
You have your first visible result. The Actor can scrape a small dataset locally before you send it anywhere else.
Did the local run fail?
Confirm that your terminal is inside the notion-results-actor directory. That directory must contain the files generated by the Actor template.
You can ask for help with your local Actor run using the error output shown after the command.
Your Actor now runs locally with dataset output you can inspect. Next up, you will push this project to Apify and run it in the Console.
Deploy and Run Your Actor
Your local Actor already scrapes a small dataset. That result proves the code works on your computer.
The Apify CLI moves that project onto Apify's cloud infrastructure. This gives the platform its own runnable copy.
You will start the deployed Actor from Apify Console. The run stores its structured records in the default Dataset.
In this step, get ready to:
- Deploy your local Actor project to Apify.
- Start the deployed Actor from Apify Console.
- View the scraped records in the run's default Dataset.
Deploy your Actor
Deployment uploads your local source to Apify. The platform builds that source into a cloud version it can run.
- Return to the terminal from your local run.
- Confirm the terminal is still inside the same Actor project folder.
- Deploy the Actor by running this command:
apify push
What does this command do?
The apify push command uploads the Actor source from your current folder. It creates the Actor in your account when needed.
The command starts a cloud build. Your terminal streams the build log while Apify prepares the deployed Actor.
Cloud builds can take a few minutes. A short pause in the log is normal.
- Wait for the CLI to finish streaming the build log.
- Open the Apify Console link printed after the build succeeds.
You should see your deployed Actor's page in Apify Console.
That is the deployment done. Your Actor now has a runnable cloud build.
Push or build stopped?
- Use the official Apify CLI quick start to restore your authenticated session.
- Inspect the final build log entry for the first file or dependency that failed.
- Ask for help with my Actor deployment.
Run your Actor in Apify Console
A successful build confirms that Apify can package your project. A Console run checks that the deployed copy can complete the same scraping job.
- Select the Input tab on the Actor page from your deployment.
- Leave the template input unchanged.
Before you start the run, do you expect the cloud version to complete the same scrape? Keep your prediction in mind.
- Click Start.
- Watch the run log until the run finishes.
You should see the cloud run finish successfully.
Run did not finish?
- Select the Log tab to inspect the run output.
- Find the first failed request near the end of the log.
- Help me troubleshoot my failed cloud run.
Check the default Dataset
The default Dataset belongs to this specific run. Its table gives you visible proof that the deployed Actor stored structured results in Apify.
Before you open the Dataset, do you expect its rows to match the records from your local terminal? Keep your prediction in mind.
- Select the Storage tab on the completed run.
- Select Dataset from the run's default storage.
You should see a table containing the small set of scraped records. The fields should match the records printed during your local run.
- Compare the visible rows with the local run output from earlier.
You have proved that the same scraper works in the cloud. Its results now persist with the Apify run.
Dataset records missing?
- Refresh the completed run page.
- Select the Storage tab again after the run has finished.
- Help me find my Actor's dataset records.
Your Actor is deployed with its results stored in Apify. Next, you will connect the destination that receives those results.
Connect Notion to Apify
Your deployed Apify Actor has completed a run in the Apify Console. Its scraped records are waiting in the run's default dataset.
Those records cannot reach Notion until Apify has permission to act in your workspace. You will authorize an MCP connector for one destination page.
In this step, get ready to:
- Choose the Notion page that will receive result comments.
- Authorize a Notion MCP connector in your Apify account.
- Save the page ID for the Actor's delivery configuration.
Choose the Notion destination
Notion identifies every page with a unique page ID. The delivery tool uses this value to place each result comment on the correct page.
Finding the page ID is a little hidden because the developer bar starts turned off. Turning on Developer Mode puts the value at the bottom of the page.
- Return to your Notion workspace from earlier.
- Select the page that should receive your Actor's result comments.
- Click Settings in the Notion sidebar.
- Search for Developer Mode.
- Turn on Developer Mode.
A developer bar now appears at the bottom of Notion. It shows the ID for the page you are viewing.
- Return to the Notion page you selected.
- Copy the page ID displayed in the developer bar.
- Record the copied value here: your Notion page ID.
Can't see the page ID?
- Make sure Developer Mode is enabled in the same Notion app where you are viewing the page.
- Return to the destination page so the developer bar shows that page's ID.
- help me find the page ID after enabling Developer Mode in Notion.
Authorize the Notion connector
An MCP connector gives Apify a reusable authorization route into Notion. OAuth lets you choose which workspace pages the connector can access.
Authorization opens a Notion consent popup. This permission screen can feel sensitive.
Your Notion password stays inside Notion's consent flow. The Actor never receives your Notion credentials.
- Switch back to the Apify Console from earlier.
- Click Settings in the left-side panel.
- Select API & Integrations.
- Find the MCP connectors section.
- Select Add connector.
- Enter https://api.notion.com/mcp as the MCP server URL.
Apify inspects the server URL. You will see OAuth as an available authentication method.
- Select OAuth.
- Sign in to Notion if the consent popup prompts you.
- Choose the Notion workspace that contains your destination page.
- Click Select pages.
- Select the same page whose ID you recorded as your Notion page ID.
- Click Allow access.
The consent popup closes after authorization. Your Notion connector is now listed as connected in Apify.
You have cleared the permission hurdle. The connector can now act within the Notion access you approved.
Authorization popup not completing?
- Allow popups for the Apify Console if the Notion consent screen does not open.
- Check the workspace name if your destination page does not appear in the page picker.
- Search for the destination page by its title inside the page picker.
- help me troubleshoot my Notion MCP connector authorization in Apify.
Confirm the connector access
Apify discovers a connector's tools during its first authorization. Seeing notion-create-comment confirms that this connector exposes the tool your Actor needs.
Before you check, do you expect the connector card to show the comment tool already?
- Expand the Notion connector card in the MCP connectors section.
You should see the connector listed as connected. Its discovered tools should include notion-create-comment.
- Switch back to your selected Notion page.
- Compare the developer bar ID with your Notion page ID.
The two page IDs should match. This confirms that your saved delivery destination is the page granted to the connector.
You have locked in both parts of the delivery route. Next, you will add the Actor code that sends its result summary to this Notion page.
Add Notion Delivery Code
Your deployed Apify Actor already scrapes a small dataset in Apify. Its useful output still stops inside the run dataset.
This step gives the Actor a delivery path into Notion through MCP. The new module sends a Markdown summary through the connector you authorised.
In this step, get ready to:
- Install the official MCP client.
- Add the Notion delivery module to the Actor.
- Push the updated source to Apify.
Prepare the delivery configuration
The official MCP SDK gives Node.js the client and transport needed to open a connector session. Your existing input schema also needs fields for the authorised connector and selected page.
- Switch back to the terminal in your local Actor project from earlier.
- Install the MCP client by running this command:
npm install @modelcontextprotocol/sdk
What does this command do?
The command adds @modelcontextprotocol/sdk to package.json. It also updates package-lock.json so the Apify build installs the same dependency.
- Wait for npm to return control to the terminal.
- Confirm package.json now lists @modelcontextprotocol/sdk under its dependencies.
Package installation failing?
- Confirm the terminal is still inside the Actor folder that contains package.json.
- Check your internet connection if the package download stalls.
- help me troubleshoot the MCP SDK installation
The connector field assigns your authorised Notion connection to each run. The page field supplies the destination used by notion-create-comment.
- Return to .actor/input_schema.json in the code editor you used earlier.
- Find the existing properties object.
- Add the notionConnector property inside properties so it matches this valid JSON object:
{
"notionConnector": {
"title": "Notion connector",
"description": "Authorized Notion MCP connector.",
"type": "string",
"resourceType": "mcpConnector",
"editor": "resourcePicker",
"mcpServers": [
{
"url": "*",
"tools": {
"required": ["notion-create-comment"]
}
}
]
}
}
How does the connector field work?
- The mcpConnector resource type renders a connector picker in the Actor input.
- The required tool rule keeps the picker focused on connectors that expose notion-create-comment.
- The selected input value gives the Actor the connector ID required by the MCP proxy.
- Add a comma after the preceding property in properties when another field appears before notionConnector.
- Save .actor/input_schema.json.
- Confirm notionConnector is nested directly under properties.
- Add the notionPageId property beside notionConnector so it matches this valid JSON object:
{
"notionPageId": {
"title": "Notion page ID",
"description": "Page that receives the result comment.",
"type": "string",
"editor": "textfield"
}
}
Why keep the page ID separate?
The connector controls which authorised Notion workspace the Actor can reach. The notionPageId field identifies the page that receives this run's comment.
- Add a comma between the notionConnector property and the notionPageId property.
- Save .actor/input_schema.json.
- Confirm the properties object now contains both delivery fields.
Seeing a JSON warning?
- Check that a comma separates the existing scraper field from notionConnector.
- Check that a comma separates notionConnector from notionPageId.
- help me fix my Actor input schema
Build the Notion delivery module
A separate delivery module keeps the connector code away from the scraper logic. The Actor can finish collecting records before this module reads the default dataset.
- Create delivery.js inside the existing src folder.
- Add the required imports to src/delivery.js by copying this code:
// Access Actor storage and logs.
import { Actor, log } from 'apify'
// Open MCP sessions through the standard client transport.
import { Client } from '@modelcontextprotocol/sdk/client/index.js'
import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js'
What do these imports provide?
- The Apify import gives the module access to the run's default dataset and log.
- The MCP imports create a client session over the proxy's Streamable HTTP transport.
- Save src/delivery.js.
- Check the module's syntax by running this command:
node --check src/delivery.js
What does a clean check mean?
The command returns to the terminal prompt without printing an error when the imports are valid JavaScript syntax. This gives you a quick check before adding the next construct.
Seeing a syntax error?
- Check that each import path matches the code block exactly.
- Confirm package.json still contains "type": "module".
- help me fix the delivery module imports
The dataset can contain objects with different fields. Converting each object to a JSON line preserves every result inside one readable summary.
- Add the summary builder below the imports in src/delivery.js by copying this code:
// Convert every dataset item into a numbered Markdown line.
function buildMarkdown(items) {
const lines = items.map((item, index) => (
`${index + 1}. \`${JSON.stringify(item)}\``
))
return [
'# Scraper results',
`Found ${items.length} records.`,
'',
...lines,
].join('\n')
}
What does this code do?
- The map() call turns each dataset object into a numbered line.
- The JSON.stringify() call preserves every field in each result.
- The returned text includes a heading and the total record count.
- Save src/delivery.js.
- Check the expanded module by running this command:
node --check src/delivery.js
What should the check show?
You should return to the terminal prompt without a syntax error. The module now has a valid summary builder.
Summary builder not passing?
- Check that the template literal around each result uses matching backticks.
- Check that the final join() call contains '\n'.
- help me fix the Markdown summary builder
The delivery function reads the completed dataset before opening an MCP session. It uses the Apify run token to authenticate to the proxy.
- Add the delivery function below buildMarkdown() in src/delivery.js by copying this code:
export async function deliverResultsToNotion({ connectorId, pageId }) {
// Read this run's default dataset after scraping finishes.
const dataset = await Actor.openDataset()
const { items } = await dataset.getData()
const markdown = buildMarkdown(items)
// Reach the authorized connector with platform-injected values.
const baseUrl = process.env.ACTOR_MCP_CONNECTOR_BASE_URL
const token = process.env.APIFY_TOKEN
const transport = new StreamableHTTPClientTransport(
new URL(`${baseUrl.replace(/\/+$/, '')}/${connectorId}`),
{ requestInit: { headers: { Authorization: `Bearer ${token}` } } },
)
const client = new Client({ name: 'notion-result-delivery', version: '1.0.0' })
await client.connect(transport)
try {
// Send the summary to the selected Notion page.
await client.callTool({
name: 'notion-create-comment',
arguments: { page_id: pageId, markdown },
})
log.info('Notion delivery completed.')
} finally {
await client.close()
}
}
How does delivery work?
- The dataset calls retrieve the records saved during the current Actor run.
- The ACTOR_MCP_CONNECTOR_BASE_URL value points to the Apify MCP proxy.
- The APIFY_TOKEN value authenticates the Actor as the user who started the run.
- The tool call sends page_id and markdown to notion-create-comment.
- Save src/delivery.js.
- Check the complete module by running this command:
node --check src/delivery.js
What should the final check show?
You should return to the terminal prompt without a syntax error. The complete delivery module is now valid JavaScript.
Delivery function not passing?
- Check that deliverResultsToNotion has one opening brace and one matching closing brace.
- Check that the regular expression inside replace() matches the code block exactly.
- help me fix the MCP delivery function
✔️ Awesome, I've got everything!
Your src/delivery.js file now reads dataset records and prepares the Notion connector call.
ⓧ I'd like to double check the full code
The complete src/delivery.js file contains the imports, summary builder, and delivery function.
// Access Actor storage and logs.
import { Actor, log } from 'apify'
// Open MCP sessions through the standard client transport.
import { Client } from '@modelcontextprotocol/sdk/client/index.js'
import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js'
// Convert every dataset item into a numbered Markdown line.
function buildMarkdown(items) {
const lines = items.map((item, index) => (
`${index + 1}. \`${JSON.stringify(item)}\``
))
return [
'# Scraper results',
`Found ${items.length} records.`,
'',
...lines,
].join('\n')
}
export async function deliverResultsToNotion({ connectorId, pageId }) {
// Read this run's default dataset after scraping finishes.
const dataset = await Actor.openDataset()
const { items } = await dataset.getData()
const markdown = buildMarkdown(items)
// Reach the authorized connector with platform-injected values.
const baseUrl = process.env.ACTOR_MCP_CONNECTOR_BASE_URL
const token = process.env.APIFY_TOKEN
const transport = new StreamableHTTPClientTransport(
new URL(`${baseUrl.replace(/\/+$/, '')}/${connectorId}`),
{ requestInit: { headers: { Authorization: `Bearer ${token}` } } },
)
const client = new Client({ name: 'notion-result-delivery', version: '1.0.0' })
await client.connect(transport)
try {
// Send the summary to the selected Notion page.
await client.callTool({
name: 'notion-create-comment',
arguments: { page_id: pageId, markdown },
})
log.info('Notion delivery completed.')
} finally {
await client.close()
}
}
The module now needs one connection to the Actor's main flow. Placing the call after scraping ensures the default dataset already contains the results.
- Return to src/main.js.
- Add this import below the existing imports at the top of the file:
// Load the delivery step after the scraper dependencies.
import { deliverResultsToNotion } from './delivery.js'
What does this import do?
The import makes deliverResultsToNotion() available to the Actor's main source. The relative path points to the new module in the same src folder.
- Find the end of the scraping flow in src/main.js.
- Add this delivery call after the scraper finishes writing its dataset:
// Read the delivery choices supplied through the Actor input.
const { notionConnector, notionPageId } = await Actor.getInput()
// Deliver only after all scraped records are in the dataset.
await deliverResultsToNotion({
connectorId: notionConnector,
pageId: notionPageId,
})
How does the main file supply configuration?
The Actor input provides the connector ID selected by the learner. It also provides the selected Notion page ID.
The delivery function maps those values to the proxy URL and the page_id argument expected by the Notion tool.
- Save src/main.js.
- Check the updated main file by running this command:
node --check src/main.js
What should the main-file check show?
You should return to the terminal prompt without a syntax error. The Actor's main source now imports and calls the delivery module.
Main file not passing?
- Check that delivery.js is inside the same src folder as main.js.
- Check that the delivery call sits outside the scraper's callback functions.
- help me place the delivery call correctly
Push the Actor and verify the build
A successful cloud build proves that Apify can install the MCP SDK and parse the updated source. It also confirms the Actor package is ready for the end-to-end run in the next step.
Cloud builds can take a few minutes while Apify installs the Actor dependencies. A quiet build screen during that time is expected.
Before you push, predict whether the cloud build will accept the new dependency and imports.
- Upload the updated Actor source and start its cloud build by running this command:
apify push
What does this command do?
The command uploads your local source to the linked Actor on Apify. Apify then starts a build using the dependencies recorded in package.json.
The terminal shows upload progress followed by build information. Wait until the command finishes before checking the Console.
- Return to the Apify Console from earlier.
- Select your deployed Actor from the Actors list.
- Click the Builds tab.
- Open the newest build.
You should see the newest build marked SUCCEEDED. That is the cloud handoff complete. Your Actor can now scrape its dataset and load the Notion delivery code.
Build not succeeding?
- Open the failed build log and find the first dependency or syntax failure.
- Confirm @modelcontextprotocol/sdk appears under dependencies in package.json.
- help me diagnose the failed Actor build
Your updated Actor now builds with its Notion delivery path in place. Next up, you will run it and watch the scraped results arrive on your selected Notion page.
Post Results to Notion
Your updated Apify Actor has passed its Console build. A successful build proves that Apify can package the delivery code.
The live run now needs to prove the full MCP delivery path. The Actor must scrape its records before the connected Notion page receives the Markdown summary.
In this step, get ready to:
- Run the updated deployed Actor.
- Verify the successful connector call in the run log.
- Confirm the results summary appears on the selected Notion page.
Test the end-to-end workflow
Each Actor run gets its own default dataset. A fresh run proves that the deployed build can scrape records with the platform configuration.
- Return to the updated Actor page in the Apify Console from earlier.
The small run may sit quietly for a few moments while the Actor completes its scrape.
Before you start, which event do you expect to appear first in the run log: the scrape or the connector call?
- Start the deployed Actor by clicking Start.
- Wait for the current run to reach a completed state.
You should see live entries in the Last run tab. The run page should report that the workflow completed successfully.
Good progress. The delivery code has now executed inside the deployed Actor.
Run Finished With an Error?
- Confirm that this run uses the build that succeeded in the previous step.
- Confirm that ACTOR_MCP_CONNECTOR_BASE_URL is available to the deployed Actor.
- Confirm that APIFY_TOKEN is available to the deployed Actor.
- Verify that the Notion connector remains authorised for the selected page.
- Help me diagnose my failed Apify Actor delivery run.
Inspect the run evidence
The run log proves that the delivery path reached notion-create-comment. The default dataset proves that the scrape still produced records.
- Select the Runs tab on the Actor page.
- Choose the run you just completed.
- Select the Log tab for that run.
- Find the notion-create-comment entry that indicates successful completion.
- Select the Storage tab for the same run.
- Open the run's Dataset.
- Compare the stored records with the small dataset from your earlier local run.
You should see the connector call in the log. You should also see the scraped records in the run's default dataset.
Together, these checks prove that scraping completed before delivery used the resulting records.
Missing the Call or Records?
- Confirm that you selected the newest run created after the successful build.
- Inspect the earlier log entries for a scrape failure if the dataset is empty.
- Verify the selected page still grants access to the Notion connector if the connector call failed.
- Help me inspect my Apify run evidence.
Close the delivery loop
The connector entry confirms that Apify completed the delivery call. The destination page provides the final proof that Notion received the summary.
Before you check Notion, do you expect the new summary to appear in the page content or the page comments?
- Switch back to the selected Notion page from earlier.
- Check the page comments for the newest entry.
- Compare the comment's summarized records with the records in the run dataset.
You should see a new comment containing the Actor's Markdown summary of the scraped results. Each summarized record should correspond to a record in the run's default dataset.
You have closed the loop. Your deployed Actor can now scrape records and deliver its own results to Notion.
Cannot See the New Comment?
- Refresh the selected Notion page to load the latest comments.
- Verify that the page you are viewing matches the page ID supplied to notion-create-comment.
- Return to the Apify run log to inspect the connector entry for a delivery failure.
- Help me find my missing Notion comment.
Your Actor now delivers its scraped results to the selected Notion page. Next, you will inspect the run's cost breakdown to see how much the delivery added.
Review Your Run Cost
Your Apify Actor has already turned a successful scrape into a comment on your selected Notion page. The final question is whether that delivery meaningfully changes the run cost.
The Apify Console exposes an itemized cost breakdown for the completed run. You will use it to isolate the MCP delivery charge.
In this step, get ready to:
- Identify the successful delivery run from its connector log entry.
- Open the run's cost breakdown.
- Confirm the delivery overhead shown for the MCP connector call.
Identify the successful delivery run
A run's cost only matters if it belongs to the workflow you just verified. The successful connector log entry anchors the cost review to the execution that created your Notion comment.
- Switch back to the successful delivery run in the Apify Console from the previous step.
- Return to the log for that run.
- Find the successful call to notion-create-comment.
You are now reviewing the same run that produced the dataset. This run also created the Notion comment.
Inspect the cost breakdown
The cost breakdown separates the scraping work from the delivery overhead. This makes the connector's marginal cost visible.
Before you open it, do you expect the connector delivery to register as a whole cent or a fraction of one?
- Open the cost breakdown from the successful run page.
- Locate the delivery charge associated with the MCP connector call.
- Read the amount shown for that delivery charge.
You should see that the delivery adds roughly one tenth of a cent to the run cost. That small line item is the incremental cost of sending the markdown summary to Notion.
That closes the loop. Your Actor now has a verified delivery cost alongside its successful result.
Can't find the delivery charge?
- Confirm that the run log contains the successful notion-create-comment call.
- Check that you opened the cost breakdown for that same run.
- Help me find the delivery charge in my successful Apify Actor run.
Your cost review is complete. The successful run now provides a complete record from scraping through delivery.
Secret mission
Audit an End-to-End Delivery
Trace one scraped value from the run dataset into its Notion comment. Use the connector log to prove execution. Use the cost breakdown to account for delivery spend.
Clean Up Your Resources
Clean Up Your Resources
The walkthrough stays within the free monthly credit described for this project. Future manual or scheduled runs use more of that credit.
Choose the cleanup level that matches what you plan to do next.
Resources you used:
- A deployed Apify Actor in your account.
- An authorised Notion MCP connector with access to your selected Notion page.
Keep everything running
No action is needed. Choose this option if you want future runs to keep posting their results to your selected Notion page.
- Leave the deployed Actor in your Apify account.
- Leave the Notion MCP connector authorised for the selected page.
- Run the Actor manually or on a schedule when you want another results comment.
Pause - I'll come back to this later
A paused state keeps the deployed Actor while removing its access to Notion. The successful run is complete, so no process remains to stop.
- Return to the Notion MCP connector from earlier in the Apify Console.
- Use the connector's revocation control to remove its Notion authorisation.
- Confirm the connector is no longer listed as connected.
- Authorise the connector again before you run the Actor's delivery workflow in the future.
Delete - I don't want to use this again
Deleting your cloud setup is permanent inside your Apify account. Your local Actor project remains on your computer, so you keep the delivery code.
- Return to the Notion MCP connector from earlier in the Apify Console.
- Use the connector's revocation control to remove its Notion authorisation.
- Confirm the connector is no longer listed as connected.
- Return to the deployed Actor from earlier in the Apify Console.
- Open the Actor's settings page.
- Use the Actor's deletion control to remove it from your Apify account.
- Return to your Actor list to confirm the deployed Actor is no longer listed.
Nice Work!
Nice Work!
You made it. Your deployed Apify Actor now scrapes a small dataset before delivering a Markdown summary to your chosen Notion page through an MCP connector.
You've learned how to:
- Created a small scraper from an Apify Actor template. Ran it locally to see dataset records in the terminal. Deployed the Actor to Apify to inspect those records in the run's dataset.
- Authorised a Notion MCP connector for your chosen page. Configured the Actor to open an MCP session with ACTOR_MCP_CONNECTOR_BASE_URL. Authenticated the session with APIFY_TOKEN. Called notion-create-comment with a Markdown summary.
- Verified the complete delivery workflow by matching the successful connector call in the run log to the new comment on your Notion page. Opened the cost breakdown to confirm that delivery added roughly one tenth of a cent.
- Secret Mission: Took on an optional challenge to push the completed Actor workflow further.
Ready to quiz yourself?